2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 *************************************************************************
35 -------- ---------- ----------------------------------------------
36 John Aug/17/04 major modification for RT2561/2661
37 Jan Lee Mar/17/06 major modification for RT2860 New Ring Design
39 #include "../rt_config.h"
43 VOID STARxEAPOLFrameIndicate(
45 IN MAC_TABLE_ENTRY *pEntry,
47 IN UCHAR FromWhichBSSID)
49 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
50 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
53 if (pAd->StaCfg.WpaSupplicantUP)
55 // All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon)
56 // TBD : process fragmented EAPol frames
58 // In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable
59 if ( pAd->StaCfg.IEEE8021X == TRUE &&
60 (EAP_CODE_SUCCESS == WpaCheckEapCode(pAd, pRxBlk->pData, pRxBlk->DataSize, LENGTH_802_1_H)))
66 DBGPRINT_RAW(RT_DEBUG_TRACE, ("Receive EAP-SUCCESS Packet\n"));
67 STA_PORT_SECURED(pAd);
69 if (pAd->StaCfg.IEEE8021x_required_keys == FALSE)
71 idx = pAd->StaCfg.DesireSharedKeyId;
72 CipherAlg = pAd->StaCfg.DesireSharedKey[idx].CipherAlg;
73 Key = pAd->StaCfg.DesireSharedKey[idx].Key;
75 if (pAd->StaCfg.DesireSharedKey[idx].KeyLen > 0)
78 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[BSSID_WCID];
80 // Set key material and cipherAlg to Asic
81 AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL);
83 // Assign group key info
84 RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL);
86 // Assign pairwise key info
87 RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, pEntry);
89 pAd->IndicateMediaState = NdisMediaStateConnected;
90 pAd->ExtraInfo = GENERAL_LINK_UP;
95 char buf[sizeof(NDIS_802_11_WEP)+MAX_LEN_OF_KEY- 1];
96 NDIS_802_11_WEP keyinfo;
101 NdisZeroMemory(&WepKey, sizeof(WepKey));
102 len =pAd->StaCfg.DesireSharedKey[idx].KeyLen;
104 NdisMoveMemory(WepKey.keyinfo.KeyMaterial,
105 pAd->StaCfg.DesireSharedKey[idx].Key,
106 pAd->StaCfg.DesireSharedKey[idx].KeyLen);
108 WepKey.keyinfo.KeyIndex = 0x80000000 + idx;
109 WepKey.keyinfo.KeyLength = len;
110 pAd->SharedKey[BSS0][idx].KeyLen =(UCHAR) (len <= 5 ? 5 : 13);
112 pAd->IndicateMediaState = NdisMediaStateConnected;
113 pAd->ExtraInfo = GENERAL_LINK_UP;
114 // need to enqueue cmd to thread
115 RTUSBEnqueueCmdFromNdis(pAd, OID_802_11_ADD_WEP, TRUE, &WepKey, sizeof(WepKey.keyinfo) + len - 1);
117 // For Preventing ShardKey Table is cleared by remove key procedure.
118 pAd->SharedKey[BSS0][idx].CipherAlg = CipherAlg;
119 pAd->SharedKey[BSS0][idx].KeyLen = pAd->StaCfg.DesireSharedKey[idx].KeyLen;
120 NdisMoveMemory(pAd->SharedKey[BSS0][idx].Key,
121 pAd->StaCfg.DesireSharedKey[idx].Key,
122 pAd->StaCfg.DesireSharedKey[idx].KeyLen);
127 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
133 // Special DATA frame that has to pass to MLME
134 // 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process
135 // 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process
137 pTmpBuf = pRxBlk->pData - LENGTH_802_11;
138 NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11);
139 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pTmpBuf, pRxBlk->DataSize + LENGTH_802_11, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
140 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! report EAPOL/AIRONET DATA to MLME (len=%d) !!!\n", pRxBlk->DataSize));
144 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
149 VOID STARxDataFrameAnnounce(
150 IN PRTMP_ADAPTER pAd,
151 IN MAC_TABLE_ENTRY *pEntry,
153 IN UCHAR FromWhichBSSID)
157 if (!RTMPCheckWPAframe(pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID))
160 // drop all non-EAP DATA frame before
161 // this client's Port-Access-Control is secured
162 if (pRxBlk->pHeader->FC.Wep)
164 // unsupported cipher suite
165 if (pAd->StaCfg.WepStatus == Ndis802_11EncryptionDisabled)
168 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
174 // encryption in-use but receive a non-EAPOL clear text frame, drop it
175 if ((pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled) &&
176 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
179 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
184 RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP);
185 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK))
187 // Normal legacy, AMPDU or AMSDU
188 CmmRxnonRalinkFrameIndicate(pAd, pRxBlk, FromWhichBSSID);
194 CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
199 RX_BLK_SET_FLAG(pRxBlk, fRX_EAP);
201 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
203 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
207 // Determin the destination of the EAP frame
208 // to WPA state machine or upper layer
209 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
215 // For TKIP frame, calculate the MIC value
216 BOOLEAN STACheckTkipMICValue(
217 IN PRTMP_ADAPTER pAd,
218 IN MAC_TABLE_ENTRY *pEntry,
221 PHEADER_802_11 pHeader = pRxBlk->pHeader;
222 UCHAR *pData = pRxBlk->pData;
223 USHORT DataSize = pRxBlk->DataSize;
224 UCHAR UserPriority = pRxBlk->UserPriority;
228 pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex];
230 pDA = pHeader->Addr1;
231 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA))
233 pSA = pHeader->Addr3;
237 pSA = pHeader->Addr2;
240 if (RTMPTkipCompareMICValue(pAd,
248 DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error 2\n"));
250 if (pAd->StaCfg.WpaSupplicantUP)
252 WpaSendMicFailureToWpaSupplicant(pAd, (pWpaKey->Type == PAIRWISEKEY) ? TRUE : FALSE);
256 RTMPReportMicError(pAd, pWpaKey);
260 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
269 // All Rx routines use RX_BLK structure to hande rx events
270 // It is very important to build pRxBlk attributes
271 // 1. pHeader pointer to 802.11 Header
272 // 2. pData pointer to payload including LLC (just skip Header)
273 // 3. set payload size including LLC to DataSize
274 // 4. set some flags with RX_BLK_SET_FLAG()
276 VOID STAHandleRxDataFrame(
277 IN PRTMP_ADAPTER pAd,
280 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
281 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
282 PHEADER_802_11 pHeader = pRxBlk->pHeader;
283 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
284 BOOLEAN bFragment = FALSE;
285 MAC_TABLE_ENTRY *pEntry = NULL;
286 UCHAR FromWhichBSSID = BSS0;
287 UCHAR UserPriority = 0;
290 // before LINK UP, all DATA frames are rejected
291 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
294 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
298 // Drop not my BSS frames
299 if (pRxD->MyBss == 0)
303 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
308 pAd->RalinkCounters.RxCountSinceLastNULL++;
309 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && (pHeader->FC.SubType & 0x08))
312 DBGPRINT(RT_DEBUG_TRACE,("bAPSDCapable\n"));
315 pData = (PUCHAR)pHeader + LENGTH_802_11;
316 if ((*pData >> 4) & 0x01)
318 DBGPRINT(RT_DEBUG_TRACE,("RxDone- Rcv EOSP frame, driver may fall into sleep\n"));
319 pAd->CommonCfg.bInServicePeriod = FALSE;
321 // Force driver to fall into sleep mode when rcv EOSP frame
322 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
324 USHORT TbttNumToNextWakeUp;
325 USHORT NextDtim = pAd->StaCfg.DtimPeriod;
328 NdisGetSystemUpTime(&Now);
329 NextDtim -= (USHORT)(Now - pAd->StaCfg.LastBeaconRxTime)/pAd->CommonCfg.BeaconPeriod;
331 TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount;
332 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim))
333 TbttNumToNextWakeUp = NextDtim;
335 MlmeSetPsmBit(pAd, PWR_SAVE);
336 // if WMM-APSD is failed, try to disable following line
337 AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp);
341 if ((pHeader->FC.MoreData) && (pAd->CommonCfg.bInServicePeriod))
343 DBGPRINT(RT_DEBUG_TRACE,("Sending another trigger frame when More Data bit is set to 1\n"));
347 // Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame
348 if ((pHeader->FC.SubType & 0x04)) // bit 2 : no DATA
351 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
355 // Drop not my BSS frame (we can not only check the MyBss bit in RxD)
359 // Infrastructure mode, check address 2 for BSSID
360 if (!RTMPEqualMemory(&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6))
362 // Receive frame not my BSSID
364 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
368 else // Ad-Hoc mode or Not associated
370 // Ad-Hoc mode, check address 3 for BSSID
371 if (!RTMPEqualMemory(&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6))
373 // Receive frame not my BSSID
375 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
383 if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE)
385 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
389 // 1. release packet if infra mode
390 // 2. new a pEntry if ad-hoc mode
391 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
398 RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA);
399 ASSERT(pRxWI->WirelessCliID == BSSID_WCID);
402 // check Atheros Client
403 if ((pEntry->bIAmBadAtheros == FALSE) && (pRxD->AMPDU == 1) && (pHeader->FC.Retry ))
405 pEntry->bIAmBadAtheros = TRUE;
406 pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE;
407 pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE;
408 if (!STA_AES_ON(pAd))
410 AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE, FALSE);
415 pRxBlk->pData = (UCHAR *)pHeader;
418 // update RxBlk->pData, DataSize
419 // 802.11 Header, QOS, HTC, Hw Padding
422 // 1. skip 802.11 HEADER
424 pRxBlk->pData += LENGTH_802_11;
425 pRxBlk->DataSize -= LENGTH_802_11;
429 if (pHeader->FC.SubType & 0x08)
431 RX_BLK_SET_FLAG(pRxBlk, fRX_QOS);
432 UserPriority = *(pRxBlk->pData) & 0x0f;
433 // bit 7 in QoS Control field signals the HT A-MSDU format
434 if ((*pRxBlk->pData) & 0x80)
436 RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU);
439 // skip QOS contorl field
441 pRxBlk->DataSize -=2;
443 pRxBlk->UserPriority = UserPriority;
445 // 3. Order bit: A-Ralink or HTC+
446 if (pHeader->FC.Order)
448 #ifdef AGGREGATION_SUPPORT
449 if ((pRxWI->PHYMODE <= MODE_OFDM) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)))
451 RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK);
456 RX_BLK_SET_FLAG(pRxBlk, fRX_HTC);
457 // skip HTC contorl field
459 pRxBlk->DataSize -= 4;
463 // 4. skip HW padding
466 // just move pData pointer
467 // because DataSize excluding HW padding
468 RX_BLK_SET_FLAG(pRxBlk, fRX_PAD);
474 RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU);
478 // Case I Process Broadcast & Multicast data frame
480 if (pRxD->Bcast || pRxD->Mcast)
482 INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount);
484 // Drop Mcast/Bcast frame with fragment bit on
485 if (pHeader->FC.MoreFrag)
488 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
492 // Filter out Bcast frame which AP relayed for us
493 if (pHeader->FC.FrDs && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress))
496 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
500 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
505 pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ;
509 pEntry = MacTableLookup(pAd, pHeader->Addr2);
511 Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI);
515 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
517 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
518 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
520 pAd->RalinkCounters.OneSecRxOkDataCnt++;
523 if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0)))
525 // re-assemble the fragmented packets
526 // return complete frame (pRxPacket) or NULL
528 pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk);
533 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
535 // process complete frame
536 if (bFragment && (pRxD->Decrypted) && (pEntry->WepStatus == Ndis802_11Encryption2Enabled))
539 pRxBlk->DataSize -= 8;
541 // For TKIP frame, calculate the MIC value
542 if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE)
548 STARxDataFrameAnnounce(pAd, pEntry, pRxBlk, FromWhichBSSID);
554 // because RTMPDeFragmentDataFrame() will release rx packet,
555 // if packet is fragmented
562 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
565 VOID STAHandleRxMgmtFrame(
566 IN PRTMP_ADAPTER pAd,
569 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
570 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
571 PHEADER_802_11 pHeader = pRxBlk->pHeader;
572 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
577 // We should collect RSSI not only U2M data but also my beacon
580 pAd->RxAnt.EvaluatePeriod == 0 &&
582 pHeader->FC.SubType == SUBTYPE_BEACON &&
583 MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2)) {
584 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
586 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
587 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
591 // collect rssi information for antenna diversity
592 if (pAd->NicConfig2.field.AntDiversity)
594 if ((pRxD->U2M) || ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2))))
596 COLLECT_RX_ANTENNA_AVERAGE_RSSI(pAd, ConvertToRssi(pAd, (UCHAR)pRxWI->RSSI0, RSSI_0), 0); //Note: RSSI2 not used on RT73
597 pAd->StaCfg.NumOfAvgRssiSample ++;
602 // First check the size, it MUST not exceed the mlme queue size
603 if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE)
605 DBGPRINT_ERR(("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount));
609 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader, pRxWI->MPDUtotalByteCount,
610 pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
613 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
616 VOID STAHandleRxControlFrame(
617 IN PRTMP_ADAPTER pAd,
620 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
621 PHEADER_802_11 pHeader = pRxBlk->pHeader;
622 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
624 switch (pHeader->FC.SubType)
626 case SUBTYPE_BLOCK_ACK_REQ:
628 CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID, (pRxWI->MPDUtotalByteCount), (PFRAME_BA_REQ)pHeader);
631 case SUBTYPE_BLOCK_ACK:
637 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
642 ========================================================================
645 Process RxDone interrupt, running in DPC level
648 pAd Pointer to our adapter
653 IRQL = DISPATCH_LEVEL
656 This routine has to maintain Rx ring read pointer.
657 Need to consider QOS DATA format when converting to 802.3
658 ========================================================================
660 BOOLEAN STARxDoneInterruptHandle(
661 IN PRTMP_ADAPTER pAd,
665 UINT32 RxProcessed, RxPending;
666 BOOLEAN bReschedule = FALSE;
667 RT28XX_RXD_STRUC *pRxD;
670 PNDIS_PACKET pRxPacket;
671 PHEADER_802_11 pHeader;
674 RxProcessed = RxPending = 0;
676 // process whole rx ring
680 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF |
681 fRTMP_ADAPTER_RESET_IN_PROGRESS |
682 fRTMP_ADAPTER_HALT_IN_PROGRESS |
683 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
684 !RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_START_UP))
690 if (RxProcessed++ > MAX_RX_PROCESS_CNT)
692 // need to reschedule rx handle
698 RxProcessed ++; // test
700 // 1. allocate a new data packet into rx ring to replace received packet
701 // then processing the received packet
702 // 2. the callee must take charge of release of packet
703 // 3. As far as driver is concerned ,
704 // the rx packet must
705 // a. be indicated to upper layer or
706 // b. be released if it is discarded
707 pRxPacket = GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule, &RxPending);
708 if (pRxPacket == NULL)
710 // no more packet to process
714 // get rx ring descriptor
715 pRxD = &(RxCell.RxD);
716 // get rx data buffer
717 pData = GET_OS_PKT_DATAPTR(pRxPacket);
718 pRxWI = (PRXWI_STRUC) pData;
719 pHeader = (PHEADER_802_11) (pData+RXWI_SIZE) ;
722 RxCell.pRxWI = pRxWI;
723 RxCell.pHeader = pHeader;
724 RxCell.pRxPacket = pRxPacket;
725 RxCell.pData = (UCHAR *) pHeader;
726 RxCell.DataSize = pRxWI->MPDUtotalByteCount;
729 // Increase Total receive byte counter after real data received no mater any error or not
730 pAd->RalinkCounters.ReceivedByteCount += pRxWI->MPDUtotalByteCount;
731 pAd->RalinkCounters.RxCount ++;
733 INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount);
735 if (pRxWI->MPDUtotalByteCount < 14)
736 Status = NDIS_STATUS_FAILURE;
740 send_monitor_packets(pAd, &RxCell);
743 /* RT2870 invokes STARxDoneInterruptHandle() in rtusb_bulk.c */
745 // Check for all RxD errors
746 Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD);
748 // Handle the received frame
749 if (Status == NDIS_STATUS_SUCCESS)
751 switch (pHeader->FC.Type)
753 // CASE I, receive a DATA frame
756 // process DATA frame
757 STAHandleRxDataFrame(pAd, &RxCell);
760 // CASE II, receive a MGMT frame
763 STAHandleRxMgmtFrame(pAd, &RxCell);
766 // CASE III. receive a CNTL frame
769 STAHandleRxControlFrame(pAd, &RxCell);
772 // discard other type
774 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
780 pAd->Counters8023.RxErrors++;
781 // discard this frame
782 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
787 // fRTMP_PS_GO_TO_SLEEP_NOW is set if receiving beacon.
788 if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW) && (INFRA_ON(pAd)))
790 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW);
791 AsicSleepThenAutoWakeup(pAd, pAd->ThisTbttNumToNextWakeUp);
799 ========================================================================
803 pAd Pointer to our adapter
805 IRQL = DISPATCH_LEVEL
807 ========================================================================
809 VOID RTMPHandleTwakeupInterrupt(
810 IN PRTMP_ADAPTER pAd)
813 AsicForceWakeup(pAd, DOT11POWERSAVE);
816 AsicForceWakeup(pAd, FALSE);
821 ========================================================================
823 Early checking and OS-depened parsing for Tx packet send to our STA driver.
826 NDIS_HANDLE MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd.
827 PPNDIS_PACKET ppPacketArray The packet array need to do transmission.
828 UINT NumberOfPackets Number of packet in packet array.
834 This function do early checking and classification for send-out packet.
835 You only can put OS-depened & STA related code in here.
836 ========================================================================
839 IN NDIS_HANDLE MiniportAdapterContext,
840 IN PPNDIS_PACKET ppPacketArray,
841 IN UINT NumberOfPackets)
844 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) MiniportAdapterContext;
845 PNDIS_PACKET pPacket;
846 BOOLEAN allowToSend = FALSE;
849 for (Index = 0; Index < NumberOfPackets; Index++)
851 pPacket = ppPacketArray[Index];
855 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
856 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
857 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
859 // Drop send request since hardware is in reset state
862 else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd))
864 // Drop send request since there are no physical connection yet
869 // Record that orignal packet source is from NDIS layer,so that
870 // later on driver knows how to release this NDIS PACKET
871 RTMP_SET_PACKET_WCID(pPacket, 0); // this field is useless when in STA mode
872 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
873 NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING);
874 pAd->RalinkCounters.PendingNdisPacketCount++;
880 if (allowToSend == TRUE)
881 STASendPacket(pAd, pPacket);
883 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
886 // Dequeue outgoing frames from TxSwQueue[] and process it
887 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
893 ========================================================================
895 This routine is used to do packet parsing and classification for Tx packet
896 to STA device, and it will en-queue packets to our TxSwQueue depends on AC
900 pAd Pointer to our adapter
901 pPacket Pointer to send packet
904 NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQueue.
905 NDIS_STATUS_FAILURE If failed to do en-queue.
908 You only can put OS-indepened & STA related code in here.
909 ========================================================================
911 NDIS_STATUS STASendPacket(
912 IN PRTMP_ADAPTER pAd,
913 IN PNDIS_PACKET pPacket)
915 PACKET_INFO PacketInfo;
920 UCHAR QueIdx, UserPriority;
921 MAC_TABLE_ENTRY *pEntry = NULL;
922 unsigned int IrqFlags;
926 // Prepare packet information structure for buffer descriptor
927 // chained within a single NDIS packet.
928 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
930 if (pSrcBufVA == NULL)
932 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n",SrcBufLen));
933 // Resourece is low, system did not allocate virtual address
934 // return NDIS_STATUS_FAILURE directly to upper layer
935 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
936 return NDIS_STATUS_FAILURE;
942 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> Ndis Packet buffer error !!!\n"));
943 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
944 return (NDIS_STATUS_FAILURE);
947 // In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry.
948 // Note multicast packets in adhoc also use BSSID_WCID index.
953 pEntry = &pAd->MacTab.Content[BSSID_WCID];
954 RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID);
955 Rate = pAd->CommonCfg.TxRate;
958 else if (ADHOC_ON(pAd))
960 if (*pSrcBufVA & 0x01)
962 RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID);
963 pEntry = &pAd->MacTab.Content[MCAST_WCID];
967 pEntry = MacTableLookup(pAd, pSrcBufVA);
969 Rate = pAd->CommonCfg.TxRate;
975 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", PRINT_MAC(pSrcBufVA)));
976 // Resourece is low, system did not allocate virtual address
977 // return NDIS_STATUS_FAILURE directly to upper layer
978 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
979 return NDIS_STATUS_FAILURE;
985 RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid);
989 // Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags.
990 // Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL).
991 RTMPCheckEtherType(pAd, pPacket);
996 // WPA 802.1x secured port control - drop all non-802.1x frame before port secured
998 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
999 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1000 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1001 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1002 || (pAd->StaCfg.IEEE8021X == TRUE)
1004 && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2))
1005 && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE)
1008 DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n"));
1009 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1011 return (NDIS_STATUS_FAILURE);
1015 // STEP 1. Decide number of fragments required to deliver this MSDU.
1016 // The estimation here is not very accurate because difficult to
1017 // take encryption overhead into consideration here. The result
1018 // "NumberOfFrag" is then just used to pre-check if enough free
1019 // TXD are available to hold this MSDU.
1022 if (*pSrcBufVA & 0x01) // fragmentation not allowed on multicast & broadcast
1024 else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))
1025 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
1026 else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED))
1027 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
1028 else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD))
1029 NumberOfFrag = 1; // MIMO RATE overwhelms fragmentation
1032 // The calculated "NumberOfFrag" is a rough estimation because of various
1033 // encryption/encapsulation overhead not taken into consideration. This number is just
1034 // used to make sure enough free TXD are available before fragmentation takes place.
1035 // In case the actual required number of fragments of an NDIS packet
1036 // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the
1037 // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of
1038 // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should
1039 // rarely happen and the penalty is just like a TX RETRY fail. Affordable.
1041 AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;
1042 NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1;
1043 // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size
1044 if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0)
1050 // Save fragment number to Ndis packet reserved field
1051 RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
1054 // STEP 2. Check the requirement of RTS:
1055 // If multiple fragment required, RTS is required only for the first fragment
1056 // if the fragment size large than RTS threshold
1057 // For RT28xx, Let ASIC send RTS/CTS
1058 RTMP_SET_PACKET_RTS(pPacket, 0);
1059 RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate);
1062 // STEP 3. Traffic classification. outcome = <UserPriority, QueIdx>
1067 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
1070 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
1071 CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE))
1075 UCHAR LlcSnapLen = 0, Byte0, Byte1;
1078 // get Ethernet protocol field
1079 Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
1080 if (Protocol <= 1500)
1082 // get Ethernet protocol field from LLC/SNAP
1083 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1086 Protocol = (USHORT)((Byte0 << 8) + Byte1);
1090 // always AC_BE for non-IP packet
1091 if (Protocol != 0x0800)
1095 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1098 // return AC_BE if packet is not IPv4
1099 if ((Byte0 & 0xf0) != 0x40)
1103 UserPriority = (Byte1 & 0xe0) >> 5;
1104 QueIdx = MapUserPriorityToAccessCategory[UserPriority];
1106 // TODO: have to check ACM bit. apply TSPEC if ACM is ON
1107 // TODO: downgrade UP & QueIdx before passing ACM
1108 if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx])
1116 RTMP_SET_PACKET_UP(pPacket, UserPriority);
1120 // Make sure SendTxWait queue resource won't be used by other threads
1121 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1122 if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE)
1124 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1125 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1127 return NDIS_STATUS_FAILURE;
1131 InsertTailQueue(&pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket));
1133 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1135 if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&&
1137 (pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE))
1143 if (((pEntry->TXBAbitmap & (1<<UserPriority)) == 0) &&
1144 ((pEntry->BADeclineBitmap & (1<<UserPriority)) == 0) &&
1145 (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
1146 // For IOT compatibility, if
1147 // 1. It is Ralink chip or
1148 // 2. It is OPEN or AES mode,
1149 // then BA session can be bulit.
1150 && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) ||
1151 (pEntry->WepStatus == Ndis802_11WEPDisabled || pEntry->WepStatus == Ndis802_11Encryption3Enabled))
1154 BAOriSessionSetUp(pAd, pEntry, 0, 0, 10, FALSE);
1158 pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed
1159 return NDIS_STATUS_SUCCESS;
1164 ========================================================================
1166 Routine Description:
1167 This subroutine will scan through releative ring descriptor to find
1168 out avaliable free ring descriptor and compare with request size.
1171 pAd Pointer to our adapter
1172 QueIdx Selected TX Ring
1175 NDIS_STATUS_FAILURE Not enough free descriptor
1176 NDIS_STATUS_SUCCESS Enough free descriptor
1178 IRQL = PASSIVE_LEVEL
1179 IRQL = DISPATCH_LEVEL
1183 ========================================================================
1188 Actually, this function used to check if the TxHardware Queue still has frame need to send.
1189 If no frame need to send, go to sleep, else, still wake up.
1192 NDIS_STATUS RTMPFreeTXDRequest(
1193 IN PRTMP_ADAPTER pAd,
1195 IN UCHAR NumberRequired,
1196 IN PUCHAR FreeNumberIs)
1199 ULONG FreeNumber = 0;
1201 NDIS_STATUS Status = NDIS_STATUS_FAILURE;
1203 unsigned long IrqFlags;
1204 HT_TX_CONTEXT *pHTTXContext;
1215 if (pAd->TxRing[QueIdx].TxSwFreeIdx > pAd->TxRing[QueIdx].TxCpuIdx)
1216 FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx - pAd->TxRing[QueIdx].TxCpuIdx - 1;
1218 FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx + TX_RING_SIZE - pAd->TxRing[QueIdx].TxCpuIdx - 1;
1220 if (FreeNumber >= NumberRequired)
1221 Status = NDIS_STATUS_SUCCESS;
1225 pHTTXContext = &pAd->TxContext[QueIdx];
1226 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1227 if ((pHTTXContext->CurWritePosition != pHTTXContext->ENextBulkOutPosition) ||
1228 (pHTTXContext->IRPPending == TRUE))
1230 Status = NDIS_STATUS_FAILURE;
1234 Status = NDIS_STATUS_SUCCESS;
1236 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1243 if (pAd->MgmtRing.TxSwFreeIdx > pAd->MgmtRing.TxCpuIdx)
1244 FreeNumber = pAd->MgmtRing.TxSwFreeIdx - pAd->MgmtRing.TxCpuIdx - 1;
1246 FreeNumber = pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE - pAd->MgmtRing.TxCpuIdx - 1;
1248 if (FreeNumber >= NumberRequired)
1249 Status = NDIS_STATUS_SUCCESS;
1252 if (pAd->MgmtRing.TxSwFreeIdx != MGMT_RING_SIZE)
1253 Status = NDIS_STATUS_FAILURE;
1255 Status = NDIS_STATUS_SUCCESS;
1260 DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1264 *FreeNumberIs = (UCHAR)FreeNumber;
1272 VOID RTMPSendDisassociationFrame(
1273 IN PRTMP_ADAPTER pAd)
1277 VOID RTMPSendNullFrame(
1278 IN PRTMP_ADAPTER pAd,
1280 IN BOOLEAN bQosNull)
1282 UCHAR NullFrame[48];
1284 PHEADER_802_11 pHeader_802_11;
1286 // WPA 802.1x secured port control
1287 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1288 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1289 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1290 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1291 || (pAd->StaCfg.IEEE8021X == TRUE)
1293 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1298 NdisZeroMemory(NullFrame, 48);
1299 Length = sizeof(HEADER_802_11);
1301 pHeader_802_11 = (PHEADER_802_11) NullFrame;
1303 pHeader_802_11->FC.Type = BTYPE_DATA;
1304 pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
1305 pHeader_802_11->FC.ToDs = 1;
1306 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1307 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1308 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1310 if (pAd->CommonCfg.bAPSDForcePowerSave)
1312 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1316 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0;
1318 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
1321 pHeader_802_11->Sequence = pAd->Sequence;
1323 // Prepare QosNull function frame
1326 pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
1328 // copy QOS control bytes
1329 NullFrame[Length] = 0;
1330 NullFrame[Length+1] = 0;
1331 Length += 2;// if pad with 2 bytes for alignment, APSD will fail
1334 HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
1338 // IRQL = DISPATCH_LEVEL
1339 VOID RTMPSendRTSFrame(
1340 IN PRTMP_ADAPTER pAd,
1342 IN unsigned int NextMpduSize,
1345 IN USHORT AckDuration,
1353 // --------------------------------------------------------
1354 // FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM
1355 // Find the WPA key, either Group or Pairwise Key
1356 // LEAP + TKIP also use WPA key.
1357 // --------------------------------------------------------
1358 // Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst
1359 // In Cisco CCX 2.0 Leap Authentication
1360 // WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey
1361 // Instead of the SharedKey, SharedKey Length may be Zero.
1362 VOID STAFindCipherAlgorithm(
1363 IN PRTMP_ADAPTER pAd,
1366 NDIS_802_11_ENCRYPTION_STATUS Cipher; // To indicate cipher used for this packet
1367 UCHAR CipherAlg = CIPHER_NONE; // cipher alogrithm
1368 UCHAR KeyIdx = 0xff;
1370 PCIPHER_KEY pKey = NULL;
1372 pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
1376 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1377 Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast
1379 Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast
1381 if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
1383 ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128);
1385 // 4-way handshaking frame must be clear
1386 if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) &&
1387 (pAd->SharedKey[BSS0][0].KeyLen))
1389 CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1393 else if (Cipher == Ndis802_11Encryption1Enabled)
1395 KeyIdx = pAd->StaCfg.DefaultKeyId;
1397 else if ((Cipher == Ndis802_11Encryption2Enabled) ||
1398 (Cipher == Ndis802_11Encryption3Enabled))
1400 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast
1401 KeyIdx = pAd->StaCfg.DefaultKeyId;
1402 else if (pAd->SharedKey[BSS0][0].KeyLen)
1405 KeyIdx = pAd->StaCfg.DefaultKeyId;
1409 CipherAlg = CIPHER_NONE;
1410 else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
1411 CipherAlg = CIPHER_NONE;
1412 else if ( pAd->StaCfg.WpaSupplicantUP &&
1413 (Cipher == Ndis802_11Encryption1Enabled) &&
1414 (pAd->StaCfg.IEEE8021X == TRUE) &&
1415 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1416 CipherAlg = CIPHER_NONE;
1419 //Header_802_11.FC.Wep = 1;
1420 CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
1421 pKey = &pAd->SharedKey[BSS0][KeyIdx];
1425 pTxBlk->CipherAlg = CipherAlg;
1426 pTxBlk->pKey = pKey;
1430 VOID STABuildCommon802_11Header(
1431 IN PRTMP_ADAPTER pAd,
1434 HEADER_802_11 *pHeader_802_11;
1437 // MAKE A COMMON 802.11 HEADER
1440 // normal wlan header size : 24 octets
1441 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1443 pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1445 NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11));
1447 pHeader_802_11->FC.FrDs = 0;
1448 pHeader_802_11->FC.Type = BTYPE_DATA;
1449 pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA);
1451 if (pTxBlk->pMacEntry)
1453 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS))
1455 pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq;
1456 pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ;
1461 pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority];
1462 pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1468 pHeader_802_11->Sequence = pAd->Sequence;
1469 pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence
1472 pHeader_802_11->Frag = 0;
1474 pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1480 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1481 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1482 COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader);
1483 pHeader_802_11->FC.ToDs = 1;
1486 else if (ADHOC_ON(pAd))
1488 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1489 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1490 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1491 pHeader_802_11->FC.ToDs = 0;
1495 if (pTxBlk->CipherAlg != CIPHER_NONE)
1496 pHeader_802_11->FC.Wep = 1;
1498 // -----------------------------------------------------------------
1499 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1500 // -----------------------------------------------------------------
1501 if (pAd->CommonCfg.bAPSDForcePowerSave)
1502 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1504 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1507 VOID STABuildCache802_11Header(
1508 IN RTMP_ADAPTER *pAd,
1512 MAC_TABLE_ENTRY *pMacEntry;
1513 PHEADER_802_11 pHeader80211;
1515 pHeader80211 = (PHEADER_802_11)pHeader;
1516 pMacEntry = pTxBlk->pMacEntry;
1519 // Update the cached 802.11 HEADER
1522 // normal wlan header size : 24 octets
1523 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1526 pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1529 pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
1530 pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1533 // The addr3 of normal packet send from DS is Dest Mac address.
1535 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1537 COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader);
1540 // -----------------------------------------------------------------
1541 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1542 // -----------------------------------------------------------------
1543 if (pAd->CommonCfg.bAPSDForcePowerSave)
1544 pHeader80211->FC.PwrMgmt = PWR_SAVE;
1546 pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1549 static inline PUCHAR STA_Build_ARalink_Frame_Header(
1550 IN RTMP_ADAPTER *pAd,
1553 PUCHAR pHeaderBufPtr;
1554 HEADER_802_11 *pHeader_802_11;
1555 PNDIS_PACKET pNextPacket;
1557 PQUEUE_ENTRY pQEntry;
1559 STAFindCipherAlgorithm(pAd, pTxBlk);
1560 STABuildCommon802_11Header(pAd, pTxBlk);
1563 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1564 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1566 // steal "order" bit to mark "aggregation"
1567 pHeader_802_11->FC.Order = 1;
1569 // skip common header
1570 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1572 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1575 // build QOS Control bytes
1577 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1579 *(pHeaderBufPtr+1) = 0;
1581 pTxBlk->MpduHeaderLen += 2;
1584 // padding at front of LLC header. LLC header should at 4-bytes aligment.
1585 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1586 pHeaderBufPtr = (PCHAR)ROUND_UP(pHeaderBufPtr, 4);
1587 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1589 // For RA Aggregation,
1590 // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format
1591 pQEntry = pTxBlk->TxPacketList.Head;
1592 pNextPacket = QUEUE_ENTRY_TO_PKT(pQEntry);
1593 nextBufLen = GET_OS_PKT_LEN(pNextPacket);
1594 if (RTMP_GET_PACKET_VLAN(pNextPacket))
1595 nextBufLen -= LENGTH_802_1Q;
1597 *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff;
1598 *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8);
1601 pTxBlk->MpduHeaderLen += 2;
1603 return pHeaderBufPtr;
1607 static inline PUCHAR STA_Build_AMSDU_Frame_Header(
1608 IN RTMP_ADAPTER *pAd,
1611 PUCHAR pHeaderBufPtr;//, pSaveBufPtr;
1612 HEADER_802_11 *pHeader_802_11;
1615 STAFindCipherAlgorithm(pAd, pTxBlk);
1616 STABuildCommon802_11Header(pAd, pTxBlk);
1618 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);
1632 *pHeaderBufPtr |= 0x80;
1634 *(pHeaderBufPtr+1) = 0;
1636 pTxBlk->MpduHeaderLen += 2;
1638 //pSaveBufPtr = pHeaderBufPtr;
1641 // padding at front of LLC header
1642 // LLC header should locate at 4-octets aligment
1644 // @@@ MpduHeaderLen excluding padding @@@
1646 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1647 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1648 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1650 return pHeaderBufPtr;
1655 VOID STA_AMPDU_Frame_Tx(
1656 IN PRTMP_ADAPTER pAd,
1659 HEADER_802_11 *pHeader_802_11;
1660 PUCHAR pHeaderBufPtr;
1662 MAC_TABLE_ENTRY *pMacEntry;
1664 PQUEUE_ENTRY pQEntry;
1668 while(pTxBlk->TxPacketList.Head)
1670 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1671 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1672 if ( RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1674 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1678 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1680 pMacEntry = pTxBlk->pMacEntry;
1681 if (pMacEntry->isCached)
1683 // NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!!
1684 NdisMoveMemory((PUCHAR)&pTxBlk->HeaderBuf[TXINFO_SIZE], (PUCHAR)&pMacEntry->CachedBuf[0], TXWI_SIZE + sizeof(HEADER_802_11));
1685 pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]);
1686 STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
1690 STAFindCipherAlgorithm(pAd, pTxBlk);
1691 STABuildCommon802_11Header(pAd, pTxBlk);
1693 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1697 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1699 // skip common header
1700 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1703 // build QOS Control bytes
1705 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1706 *(pHeaderBufPtr+1) = 0;
1708 pTxBlk->MpduHeaderLen += 2;
1712 // HTC control filed following QoS field
1714 if ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))
1716 if (pMacEntry->isCached == FALSE)
1719 pHeader_802_11->FC.Order = 1;
1721 NdisZeroMemory(pHeaderBufPtr, 4);
1722 *(pHeaderBufPtr+3) |= 0x80;
1725 pTxBlk->MpduHeaderLen += 4;
1728 //pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE;
1729 ASSERT(pTxBlk->MpduHeaderLen >= 24);
1731 // skip 802.3 header
1732 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1733 pTxBlk->SrcBufLen -= LENGTH_802_3;
1738 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1739 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1743 // padding at front of LLC header
1744 // LLC header should locate at 4-octets aligment
1746 // @@@ MpduHeaderLen excluding padding @@@
1748 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1749 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1750 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1755 // Insert LLC-SNAP encapsulation - 8 octets
1757 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1758 if (pTxBlk->pExtraLlcSnapEncap)
1760 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1762 // get 2 octets (TypeofLen)
1763 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1765 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1770 if (pMacEntry->isCached)
1772 RTMPWriteTxWI_Cache(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1776 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1778 NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf));
1779 NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE])));
1780 pMacEntry->isCached = TRUE;
1783 // calculate Transmitted AMPDU count and ByteCount
1785 pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++;
1786 pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen;
1789 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1791 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1797 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
1799 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1801 pAd->RalinkCounters.KickTxCount++;
1802 pAd->RalinkCounters.OneSecTxDoneCount++;
1808 VOID STA_AMSDU_Frame_Tx(
1809 IN PRTMP_ADAPTER pAd,
1812 PUCHAR pHeaderBufPtr;
1814 USHORT subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding.
1815 USHORT totalMPDUSize=0;
1816 UCHAR *subFrameHeader;
1818 USHORT FirstTx = 0, LastTxIdx = 0;
1821 PQUEUE_ENTRY pQEntry;
1826 ASSERT((pTxBlk->TxPacketList.Number > 1));
1828 while(pTxBlk->TxPacketList.Head)
1830 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1831 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1832 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1834 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1838 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1840 // skip 802.3 header
1841 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1842 pTxBlk->SrcBufLen -= LENGTH_802_3;
1847 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1848 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1853 pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
1855 // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled.
1856 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1860 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
1861 padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen);
1862 NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD);
1863 pHeaderBufPtr += padding;
1864 pTxBlk->MpduHeaderLen = padding;
1869 // DA(6)+SA(6)+Length(2) + LLC/SNAP Encap
1871 subFrameHeader = pHeaderBufPtr;
1872 subFramePayloadLen = pTxBlk->SrcBufLen;
1874 NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
1877 pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
1878 pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
1882 // Insert LLC-SNAP encapsulation - 8 octets
1884 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1886 subFramePayloadLen = pTxBlk->SrcBufLen;
1888 if (pTxBlk->pExtraLlcSnapEncap)
1890 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1892 // get 2 octets (TypeofLen)
1893 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1895 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1896 subFramePayloadLen += LENGTH_802_1_H;
1899 // update subFrame Length field
1900 subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
1901 subFrameHeader[13] = subFramePayloadLen & 0xFF;
1903 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1906 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1908 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1912 pAd->RalinkCounters.KickTxCount++;
1913 pAd->RalinkCounters.OneSecTxDoneCount++;
1915 // calculate Transmitted AMSDU Count and ByteCount
1917 pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++;
1918 pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize;
1923 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
1924 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
1930 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
1932 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1935 VOID STA_Legacy_Frame_Tx(
1936 IN PRTMP_ADAPTER pAd,
1939 HEADER_802_11 *pHeader_802_11;
1940 PUCHAR pHeaderBufPtr;
1943 PQUEUE_ENTRY pQEntry;
1948 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1949 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1950 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1952 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1956 if (pTxBlk->TxFrameType == TX_MCAST_FRAME)
1958 INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
1961 if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
1962 TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
1964 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
1966 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1968 if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
1969 pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
1971 STAFindCipherAlgorithm(pAd, pTxBlk);
1972 STABuildCommon802_11Header(pAd, pTxBlk);
1975 // skip 802.3 header
1976 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1977 pTxBlk->SrcBufLen -= LENGTH_802_3;
1982 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1983 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1986 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1987 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1989 // skip common header
1990 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1992 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1995 // build QOS Control bytes
1997 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1998 *(pHeaderBufPtr+1) = 0;
2000 pTxBlk->MpduHeaderLen += 2;
2003 // The remaining content of MPDU header should locate at 4-octets aligment
2004 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2005 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2006 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2011 // Insert LLC-SNAP encapsulation - 8 octets
2014 // if original Ethernet frame contains no LLC/SNAP,
2015 // then an extra LLC/SNAP encap is required
2017 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2018 if (pTxBlk->pExtraLlcSnapEncap)
2022 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2025 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2026 // get 2 octets (TypeofLen)
2027 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2029 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2036 // use Wcid as Key Index
2039 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2041 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2043 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
2045 pAd->RalinkCounters.KickTxCount++;
2046 pAd->RalinkCounters.OneSecTxDoneCount++;
2052 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2054 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2058 VOID STA_ARalink_Frame_Tx(
2059 IN PRTMP_ADAPTER pAd,
2062 PUCHAR pHeaderBufPtr;
2064 USHORT totalMPDUSize=0;
2065 USHORT FirstTx, LastTxIdx;
2068 PQUEUE_ENTRY pQEntry;
2073 ASSERT((pTxBlk->TxPacketList.Number== 2));
2076 FirstTx = LastTxIdx = 0; // Is it ok init they as 0?
2077 while(pTxBlk->TxPacketList.Head)
2079 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2080 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2082 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2084 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2088 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2090 // skip 802.3 header
2091 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2092 pTxBlk->SrcBufLen -= LENGTH_802_3;
2097 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2098 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2102 { // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header
2104 pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
2106 // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount
2107 // will be updated after final frame was handled.
2108 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2112 // Insert LLC-SNAP encapsulation - 8 octets
2114 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
2116 if (pTxBlk->pExtraLlcSnapEncap)
2118 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2120 // get 2 octets (TypeofLen)
2121 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2123 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2127 { // For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0.
2129 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
2130 pTxBlk->MpduHeaderLen = 0;
2132 // A-Ralink sub-sequent frame header is the same as 802.3 header.
2133 // DA(6)+SA(6)+FrameType(2)
2134 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12);
2135 pHeaderBufPtr += 12;
2136 // get 2 octets (TypeofLen)
2137 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2139 pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD;
2142 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2144 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2146 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2148 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2152 pAd->RalinkCounters.OneSecTxAggregationCount++;
2153 pAd->RalinkCounters.KickTxCount++;
2154 pAd->RalinkCounters.OneSecTxDoneCount++;
2158 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2159 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2165 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2167 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2172 VOID STA_Fragment_Frame_Tx(
2173 IN RTMP_ADAPTER *pAd,
2176 HEADER_802_11 *pHeader_802_11;
2177 PUCHAR pHeaderBufPtr;
2180 PACKET_INFO PacketInfo;
2181 USHORT EncryptionOverhead = 0;
2182 UINT32 FreeMpduSize, SrcRemainingBytes;
2186 PQUEUE_ENTRY pQEntry;
2191 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2192 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2193 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2195 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2199 ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag));
2200 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2202 STAFindCipherAlgorithm(pAd, pTxBlk);
2203 STABuildCommon802_11Header(pAd, pTxBlk);
2205 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2207 pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket);
2208 if (pTxBlk->pPacket == NULL)
2210 RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
2213 // skip 802.3 header
2214 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2215 pTxBlk->SrcBufLen -= LENGTH_802_3;
2221 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2222 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2225 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2226 pHeader_802_11 = (HEADER_802_11 *)pHeaderBufPtr;
2229 // skip common header
2230 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2232 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2235 // build QOS Control bytes
2237 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2239 *(pHeaderBufPtr+1) = 0;
2241 pTxBlk->MpduHeaderLen += 2;
2245 // padding at front of LLC header
2246 // LLC header should locate at 4-octets aligment
2248 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2249 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2250 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2255 // Insert LLC-SNAP encapsulation - 8 octets
2258 // if original Ethernet frame contains no LLC/SNAP,
2259 // then an extra LLC/SNAP encap is required
2261 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2262 if (pTxBlk->pExtraLlcSnapEncap)
2266 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2269 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2270 // get 2 octets (TypeofLen)
2271 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2273 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2277 // If TKIP is used and fragmentation is required. Driver has to
2278 // append TKIP MIC at tail of the scatter buffer
2279 // MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC
2280 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2283 // NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust
2284 // to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress.
2285 NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8);
2286 //skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8);
2287 pTxBlk->SrcBufLen += 8;
2288 pTxBlk->TotalFrameLen += 8;
2289 pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC;
2293 // calcuate the overhead bytes that encryption algorithm may add. This
2294 // affects the calculate of "duration" field
2296 if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128))
2297 EncryptionOverhead = 8; //WEP: IV[4] + ICV[4];
2298 else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC)
2299 EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength
2300 else if (pTxBlk->CipherAlg == CIPHER_TKIP)
2301 EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8]
2302 else if (pTxBlk->CipherAlg == CIPHER_AES)
2303 EncryptionOverhead = 16; // AES: IV[4] + EIV[4] + MIC[8]
2305 EncryptionOverhead = 0;
2307 // decide how much time an ACK/CTS frame will consume in the air
2308 AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14);
2310 // Init the total payload length of this frame.
2311 SrcRemainingBytes = pTxBlk->SrcBufLen;
2313 pTxBlk->TotalFragNum = 0xff;
2317 FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC;
2319 FreeMpduSize -= pTxBlk->MpduHeaderLen;
2321 if (SrcRemainingBytes <= FreeMpduSize)
2322 { // this is the last or only fragment
2324 pTxBlk->SrcBufLen = SrcRemainingBytes;
2326 pHeader_802_11->FC.MoreFrag = 0;
2327 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + AckDuration;
2329 // Indicate the lower layer that this's the last fragment.
2330 pTxBlk->TotalFragNum = fragNum;
2333 { // more fragment is required
2335 pTxBlk->SrcBufLen = FreeMpduSize;
2337 NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), ((UINT)pAd->CommonCfg.FragmentThreshold));
2338 pHeader_802_11->FC.MoreFrag = 1;
2339 pHeader_802_11->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead);
2343 pTxBlk->FrameGap = IFS_HTTXOP;
2345 pTxBlk->FrameGap = IFS_SIFS;
2347 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2349 HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber);
2351 pAd->RalinkCounters.KickTxCount++;
2352 pAd->RalinkCounters.OneSecTxDoneCount++;
2354 // Update the frame number, remaining size of the NDIS packet payload.
2356 // space for 802.11 header.
2357 if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap)
2358 pTxBlk->MpduHeaderLen -= LENGTH_802_1_H;
2361 SrcRemainingBytes -= pTxBlk->SrcBufLen;
2362 pTxBlk->pSrcBufData += pTxBlk->SrcBufLen;
2364 pHeader_802_11->Frag++; // increase Frag #
2366 }while(SrcRemainingBytes > 0);
2371 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2375 #define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \
2376 while(_pTxBlk->TxPacketList.Head) \
2378 _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList); \
2379 RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \
2384 ========================================================================
2386 Routine Description:
2387 Copy frame from waiting queue into relative ring buffer and set
2388 appropriate ASIC register to kick hardware encryption before really
2392 pAd Pointer to our adapter
2393 PNDIS_PACKET Pointer to outgoing Ndis frame
2394 NumberOfFrag Number of fragment required
2399 IRQL = DISPATCH_LEVEL
2403 ========================================================================
2405 NDIS_STATUS STAHardTransmit(
2406 IN PRTMP_ADAPTER pAd,
2410 NDIS_PACKET *pPacket;
2411 PQUEUE_ENTRY pQEntry;
2413 // ---------------------------------------------
2414 // STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION.
2415 // ---------------------------------------------
2417 ASSERT(pTxBlk->TxPacketList.Number);
2418 if (pTxBlk->TxPacketList.Head == NULL)
2420 DBGPRINT(RT_DEBUG_ERROR, ("pTxBlk->TotalFrameNum == %ld!\n", pTxBlk->TxPacketList.Number));
2421 return NDIS_STATUS_FAILURE;
2424 pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head);
2426 // ------------------------------------------------------------------
2427 // STEP 1. WAKE UP PHY
2428 // outgoing frame always wakeup PHY to prevent frame lost and
2429 // turn off PSM bit to improve performance
2430 // ------------------------------------------------------------------
2431 // not to change PSM bit, just send this frame out?
2432 if ((pAd->StaCfg.Psm == PWR_SAVE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2434 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicForceWakeup At HardTx\n"));
2436 AsicForceWakeup(pAd, FROM_TX);
2439 AsicForceWakeup(pAd, TRUE);
2443 // It should not change PSM bit, when APSD turn on.
2444 if ((!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE))
2445 || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
2446 || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket)))
2448 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
2449 (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeFast_PSP))
2450 MlmeSetPsmBit(pAd, PWR_ACTIVE);
2453 switch (pTxBlk->TxFrameType)
2455 case TX_AMPDU_FRAME:
2456 STA_AMPDU_Frame_Tx(pAd, pTxBlk);
2458 case TX_AMSDU_FRAME:
2459 STA_AMSDU_Frame_Tx(pAd, pTxBlk);
2461 case TX_LEGACY_FRAME:
2462 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2464 case TX_MCAST_FRAME:
2465 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2467 case TX_RALINK_FRAME:
2468 STA_ARalink_Frame_Tx(pAd, pTxBlk);
2471 STA_Fragment_Frame_Tx(pAd, pTxBlk);
2475 // It should not happened!
2476 DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!! It should not happen!\n"));
2477 while(pTxBlk->TxPacketList.Number)
2479 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2480 pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2482 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2488 return (NDIS_STATUS_SUCCESS);
2492 ULONG HashBytesPolynomial(UCHAR *value, unsigned int len)
2494 unsigned char *word = value;
2495 unsigned int ret = 0;
2498 for(i=0; i < len; i++)
2501 ret ^=(unsigned int) (word[i]) << mod;
2502 ret ^=(unsigned int) (word[i]) >> (32 - mod);
2507 VOID Sta_Announce_or_Forward_802_3_Packet(
2508 IN PRTMP_ADAPTER pAd,
2509 IN PNDIS_PACKET pPacket,
2510 IN UCHAR FromWhichBSSID)
2515 announce_802_3_packet(pAd, pPacket);
2520 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);