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)
77 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[BSSID_WCID];
79 // Set key material and cipherAlg to Asic
80 AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL);
82 // Assign group key info
83 RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL);
85 // Assign pairwise key info
86 RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, pEntry);
88 pAd->IndicateMediaState = NdisMediaStateConnected;
89 pAd->ExtraInfo = GENERAL_LINK_UP;
90 // For Preventing ShardKey Table is cleared by remove key procedure.
91 pAd->SharedKey[BSS0][idx].CipherAlg = CipherAlg;
92 pAd->SharedKey[BSS0][idx].KeyLen = pAd->StaCfg.DesireSharedKey[idx].KeyLen;
93 NdisMoveMemory(pAd->SharedKey[BSS0][idx].Key,
94 pAd->StaCfg.DesireSharedKey[idx].Key,
95 pAd->StaCfg.DesireSharedKey[idx].KeyLen);
100 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
106 // Special DATA frame that has to pass to MLME
107 // 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process
108 // 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process
110 pTmpBuf = pRxBlk->pData - LENGTH_802_11;
111 NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11);
112 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pTmpBuf, pRxBlk->DataSize + LENGTH_802_11, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
113 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! report EAPOL/AIRONET DATA to MLME (len=%d) !!!\n", pRxBlk->DataSize));
117 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
122 VOID STARxDataFrameAnnounce(
123 IN PRTMP_ADAPTER pAd,
124 IN MAC_TABLE_ENTRY *pEntry,
126 IN UCHAR FromWhichBSSID)
130 if (!RTMPCheckWPAframe(pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID))
133 // drop all non-EAP DATA frame before
134 // this client's Port-Access-Control is secured
135 if (pRxBlk->pHeader->FC.Wep)
137 // unsupported cipher suite
138 if (pAd->StaCfg.WepStatus == Ndis802_11EncryptionDisabled)
141 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
147 // encryption in-use but receive a non-EAPOL clear text frame, drop it
148 if ((pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled) &&
149 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
152 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
157 RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP);
158 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK))
160 // Normal legacy, AMPDU or AMSDU
161 CmmRxnonRalinkFrameIndicate(pAd, pRxBlk, FromWhichBSSID);
167 CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
172 RX_BLK_SET_FLAG(pRxBlk, fRX_EAP);
174 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
176 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
180 // Determin the destination of the EAP frame
181 // to WPA state machine or upper layer
182 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
188 // For TKIP frame, calculate the MIC value
189 BOOLEAN STACheckTkipMICValue(
190 IN PRTMP_ADAPTER pAd,
191 IN MAC_TABLE_ENTRY *pEntry,
194 PHEADER_802_11 pHeader = pRxBlk->pHeader;
195 UCHAR *pData = pRxBlk->pData;
196 USHORT DataSize = pRxBlk->DataSize;
197 UCHAR UserPriority = pRxBlk->UserPriority;
201 pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex];
203 pDA = pHeader->Addr1;
204 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA))
206 pSA = pHeader->Addr3;
210 pSA = pHeader->Addr2;
213 if (RTMPTkipCompareMICValue(pAd,
221 DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error 2\n"));
223 if (pAd->StaCfg.WpaSupplicantUP)
225 WpaSendMicFailureToWpaSupplicant(pAd, (pWpaKey->Type == PAIRWISEKEY) ? TRUE : FALSE);
229 RTMPReportMicError(pAd, pWpaKey);
233 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
242 // All Rx routines use RX_BLK structure to hande rx events
243 // It is very important to build pRxBlk attributes
244 // 1. pHeader pointer to 802.11 Header
245 // 2. pData pointer to payload including LLC (just skip Header)
246 // 3. set payload size including LLC to DataSize
247 // 4. set some flags with RX_BLK_SET_FLAG()
249 VOID STAHandleRxDataFrame(
250 IN PRTMP_ADAPTER pAd,
253 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
254 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
255 PHEADER_802_11 pHeader = pRxBlk->pHeader;
256 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
257 BOOLEAN bFragment = FALSE;
258 MAC_TABLE_ENTRY *pEntry = NULL;
259 UCHAR FromWhichBSSID = BSS0;
260 UCHAR UserPriority = 0;
263 // before LINK UP, all DATA frames are rejected
264 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
267 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
271 // Drop not my BSS frames
272 if (pRxD->MyBss == 0)
276 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
281 pAd->RalinkCounters.RxCountSinceLastNULL++;
282 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && (pHeader->FC.SubType & 0x08))
285 DBGPRINT(RT_DEBUG_TRACE,("bAPSDCapable\n"));
288 pData = (PUCHAR)pHeader + LENGTH_802_11;
289 if ((*pData >> 4) & 0x01)
291 DBGPRINT(RT_DEBUG_TRACE,("RxDone- Rcv EOSP frame, driver may fall into sleep\n"));
292 pAd->CommonCfg.bInServicePeriod = FALSE;
294 // Force driver to fall into sleep mode when rcv EOSP frame
295 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
297 USHORT TbttNumToNextWakeUp;
298 USHORT NextDtim = pAd->StaCfg.DtimPeriod;
301 NdisGetSystemUpTime(&Now);
302 NextDtim -= (USHORT)(Now - pAd->StaCfg.LastBeaconRxTime)/pAd->CommonCfg.BeaconPeriod;
304 TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount;
305 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim))
306 TbttNumToNextWakeUp = NextDtim;
308 MlmeSetPsmBit(pAd, PWR_SAVE);
309 // if WMM-APSD is failed, try to disable following line
310 AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp);
314 if ((pHeader->FC.MoreData) && (pAd->CommonCfg.bInServicePeriod))
316 DBGPRINT(RT_DEBUG_TRACE,("Sending another trigger frame when More Data bit is set to 1\n"));
320 // Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame
321 if ((pHeader->FC.SubType & 0x04)) // bit 2 : no DATA
324 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
328 // Drop not my BSS frame (we can not only check the MyBss bit in RxD)
332 // Infrastructure mode, check address 2 for BSSID
333 if (!RTMPEqualMemory(&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6))
335 // Receive frame not my BSSID
337 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
341 else // Ad-Hoc mode or Not associated
343 // Ad-Hoc mode, check address 3 for BSSID
344 if (!RTMPEqualMemory(&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6))
346 // Receive frame not my BSSID
348 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
356 if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE)
358 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
362 // 1. release packet if infra mode
363 // 2. new a pEntry if ad-hoc mode
364 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
371 RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA);
372 ASSERT(pRxWI->WirelessCliID == BSSID_WCID);
375 // check Atheros Client
376 if ((pEntry->bIAmBadAtheros == FALSE) && (pRxD->AMPDU == 1) && (pHeader->FC.Retry ))
378 pEntry->bIAmBadAtheros = TRUE;
379 pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE;
380 pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE;
381 if (!STA_AES_ON(pAd))
383 AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE, FALSE);
388 pRxBlk->pData = (UCHAR *)pHeader;
391 // update RxBlk->pData, DataSize
392 // 802.11 Header, QOS, HTC, Hw Padding
395 // 1. skip 802.11 HEADER
397 pRxBlk->pData += LENGTH_802_11;
398 pRxBlk->DataSize -= LENGTH_802_11;
402 if (pHeader->FC.SubType & 0x08)
404 RX_BLK_SET_FLAG(pRxBlk, fRX_QOS);
405 UserPriority = *(pRxBlk->pData) & 0x0f;
406 // bit 7 in QoS Control field signals the HT A-MSDU format
407 if ((*pRxBlk->pData) & 0x80)
409 RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU);
412 // skip QOS contorl field
414 pRxBlk->DataSize -=2;
416 pRxBlk->UserPriority = UserPriority;
418 // 3. Order bit: A-Ralink or HTC+
419 if (pHeader->FC.Order)
421 #ifdef AGGREGATION_SUPPORT
422 if ((pRxWI->PHYMODE <= MODE_OFDM) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)))
424 RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK);
429 RX_BLK_SET_FLAG(pRxBlk, fRX_HTC);
430 // skip HTC contorl field
432 pRxBlk->DataSize -= 4;
436 // 4. skip HW padding
439 // just move pData pointer
440 // because DataSize excluding HW padding
441 RX_BLK_SET_FLAG(pRxBlk, fRX_PAD);
447 RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU);
451 // Case I Process Broadcast & Multicast data frame
453 if (pRxD->Bcast || pRxD->Mcast)
455 INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount);
457 // Drop Mcast/Bcast frame with fragment bit on
458 if (pHeader->FC.MoreFrag)
461 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
465 // Filter out Bcast frame which AP relayed for us
466 if (pHeader->FC.FrDs && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress))
469 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
473 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
478 pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ;
482 pEntry = MacTableLookup(pAd, pHeader->Addr2);
484 Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI);
488 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
490 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
491 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
493 pAd->RalinkCounters.OneSecRxOkDataCnt++;
496 if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0)))
498 // re-assemble the fragmented packets
499 // return complete frame (pRxPacket) or NULL
501 pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk);
506 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
508 // process complete frame
509 if (bFragment && (pRxD->Decrypted) && (pEntry->WepStatus == Ndis802_11Encryption2Enabled))
512 pRxBlk->DataSize -= 8;
514 // For TKIP frame, calculate the MIC value
515 if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE)
521 STARxDataFrameAnnounce(pAd, pEntry, pRxBlk, FromWhichBSSID);
527 // because RTMPDeFragmentDataFrame() will release rx packet,
528 // if packet is fragmented
535 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
538 VOID STAHandleRxMgmtFrame(
539 IN PRTMP_ADAPTER pAd,
542 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
543 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
544 PHEADER_802_11 pHeader = pRxBlk->pHeader;
545 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
550 // We should collect RSSI not only U2M data but also my beacon
551 if ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2)))
553 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
555 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
556 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
559 // First check the size, it MUST not exceed the mlme queue size
560 if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE)
562 DBGPRINT_ERR(("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount));
566 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader, pRxWI->MPDUtotalByteCount,
567 pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
570 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
573 VOID STAHandleRxControlFrame(
574 IN PRTMP_ADAPTER pAd,
577 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
578 PHEADER_802_11 pHeader = pRxBlk->pHeader;
579 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
581 switch (pHeader->FC.SubType)
583 case SUBTYPE_BLOCK_ACK_REQ:
585 CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID, (pRxWI->MPDUtotalByteCount), (PFRAME_BA_REQ)pHeader);
588 case SUBTYPE_BLOCK_ACK:
594 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
599 ========================================================================
602 Process RxDone interrupt, running in DPC level
605 pAd Pointer to our adapter
610 IRQL = DISPATCH_LEVEL
613 This routine has to maintain Rx ring read pointer.
614 Need to consider QOS DATA format when converting to 802.3
615 ========================================================================
617 BOOLEAN STARxDoneInterruptHandle(
618 IN PRTMP_ADAPTER pAd,
622 UINT32 RxProcessed, RxPending;
623 BOOLEAN bReschedule = FALSE;
624 RT28XX_RXD_STRUC *pRxD;
627 PNDIS_PACKET pRxPacket;
628 PHEADER_802_11 pHeader;
631 RxProcessed = RxPending = 0;
633 // process whole rx ring
637 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF |
638 fRTMP_ADAPTER_RESET_IN_PROGRESS |
639 fRTMP_ADAPTER_HALT_IN_PROGRESS |
640 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
641 !RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_START_UP))
646 if (RxProcessed++ > MAX_RX_PROCESS_CNT)
648 // need to reschedule rx handle
653 RxProcessed ++; // test
655 // 1. allocate a new data packet into rx ring to replace received packet
656 // then processing the received packet
657 // 2. the callee must take charge of release of packet
658 // 3. As far as driver is concerned ,
659 // the rx packet must
660 // a. be indicated to upper layer or
661 // b. be released if it is discarded
662 pRxPacket = GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule, &RxPending);
663 if (pRxPacket == NULL)
665 // no more packet to process
669 // get rx ring descriptor
670 pRxD = &(RxCell.RxD);
671 // get rx data buffer
672 pData = GET_OS_PKT_DATAPTR(pRxPacket);
673 pRxWI = (PRXWI_STRUC) pData;
674 pHeader = (PHEADER_802_11) (pData+RXWI_SIZE) ;
677 RxCell.pRxWI = pRxWI;
678 RxCell.pHeader = pHeader;
679 RxCell.pRxPacket = pRxPacket;
680 RxCell.pData = (UCHAR *) pHeader;
681 RxCell.DataSize = pRxWI->MPDUtotalByteCount;
684 // Increase Total receive byte counter after real data received no mater any error or not
685 pAd->RalinkCounters.ReceivedByteCount += pRxWI->MPDUtotalByteCount;
686 pAd->RalinkCounters.RxCount ++;
688 INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount);
690 if (pRxWI->MPDUtotalByteCount < 14)
691 Status = NDIS_STATUS_FAILURE;
695 send_monitor_packets(pAd, &RxCell);
698 /* RT2870 invokes STARxDoneInterruptHandle() in rtusb_bulk.c */
700 // Check for all RxD errors
701 Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD);
703 // Handle the received frame
704 if (Status == NDIS_STATUS_SUCCESS)
706 switch (pHeader->FC.Type)
708 // CASE I, receive a DATA frame
711 // process DATA frame
712 STAHandleRxDataFrame(pAd, &RxCell);
715 // CASE II, receive a MGMT frame
718 STAHandleRxMgmtFrame(pAd, &RxCell);
721 // CASE III. receive a CNTL frame
724 STAHandleRxControlFrame(pAd, &RxCell);
727 // discard other type
729 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
735 pAd->Counters8023.RxErrors++;
736 // discard this frame
737 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
741 // fRTMP_PS_GO_TO_SLEEP_NOW is set if receiving beacon.
742 if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW) && (INFRA_ON(pAd)))
744 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW);
745 AsicSleepThenAutoWakeup(pAd, pAd->ThisTbttNumToNextWakeUp);
752 ========================================================================
756 pAd Pointer to our adapter
758 IRQL = DISPATCH_LEVEL
760 ========================================================================
762 VOID RTMPHandleTwakeupInterrupt(
763 IN PRTMP_ADAPTER pAd)
765 AsicForceWakeup(pAd, DOT11POWERSAVE);
769 ========================================================================
771 Early checking and OS-depened parsing for Tx packet send to our STA driver.
774 NDIS_HANDLE MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd.
775 PPNDIS_PACKET ppPacketArray The packet array need to do transmission.
776 UINT NumberOfPackets Number of packet in packet array.
782 This function do early checking and classification for send-out packet.
783 You only can put OS-depened & STA related code in here.
784 ========================================================================
787 IN NDIS_HANDLE MiniportAdapterContext,
788 IN PPNDIS_PACKET ppPacketArray,
789 IN UINT NumberOfPackets)
792 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) MiniportAdapterContext;
793 PNDIS_PACKET pPacket;
794 BOOLEAN allowToSend = FALSE;
797 for (Index = 0; Index < NumberOfPackets; Index++)
799 pPacket = ppPacketArray[Index];
803 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
804 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
805 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
807 // Drop send request since hardware is in reset state
810 else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd))
812 // Drop send request since there are no physical connection yet
817 // Record that orignal packet source is from NDIS layer,so that
818 // later on driver knows how to release this NDIS PACKET
819 RTMP_SET_PACKET_WCID(pPacket, 0); // this field is useless when in STA mode
820 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
821 NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING);
822 pAd->RalinkCounters.PendingNdisPacketCount++;
828 if (allowToSend == TRUE)
829 STASendPacket(pAd, pPacket);
831 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
834 // Dequeue outgoing frames from TxSwQueue[] and process it
835 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
841 ========================================================================
843 This routine is used to do packet parsing and classification for Tx packet
844 to STA device, and it will en-queue packets to our TxSwQueue depends on AC
848 pAd Pointer to our adapter
849 pPacket Pointer to send packet
852 NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQueue.
853 NDIS_STATUS_FAILURE If failed to do en-queue.
856 You only can put OS-indepened & STA related code in here.
857 ========================================================================
859 NDIS_STATUS STASendPacket(
860 IN PRTMP_ADAPTER pAd,
861 IN PNDIS_PACKET pPacket)
863 PACKET_INFO PacketInfo;
868 UCHAR QueIdx, UserPriority;
869 MAC_TABLE_ENTRY *pEntry = NULL;
870 unsigned int IrqFlags;
874 // Prepare packet information structure for buffer descriptor
875 // chained within a single NDIS packet.
876 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
878 if (pSrcBufVA == NULL)
880 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n",SrcBufLen));
881 // Resourece is low, system did not allocate virtual address
882 // return NDIS_STATUS_FAILURE directly to upper layer
883 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
884 return NDIS_STATUS_FAILURE;
890 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> Ndis Packet buffer error !!!\n"));
891 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
892 return (NDIS_STATUS_FAILURE);
895 // In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry.
896 // Note multicast packets in adhoc also use BSSID_WCID index.
901 pEntry = &pAd->MacTab.Content[BSSID_WCID];
902 RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID);
903 Rate = pAd->CommonCfg.TxRate;
906 else if (ADHOC_ON(pAd))
908 if (*pSrcBufVA & 0x01)
910 RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID);
911 pEntry = &pAd->MacTab.Content[MCAST_WCID];
915 pEntry = MacTableLookup(pAd, pSrcBufVA);
917 Rate = pAd->CommonCfg.TxRate;
923 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", PRINT_MAC(pSrcBufVA)));
924 // Resourece is low, system did not allocate virtual address
925 // return NDIS_STATUS_FAILURE directly to upper layer
926 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
927 return NDIS_STATUS_FAILURE;
933 RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid);
937 // Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags.
938 // Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL).
939 RTMPCheckEtherType(pAd, pPacket);
944 // WPA 802.1x secured port control - drop all non-802.1x frame before port secured
946 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
947 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
948 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
949 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
950 || (pAd->StaCfg.IEEE8021X == TRUE)
952 && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2))
953 && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE)
956 DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n"));
957 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
959 return (NDIS_STATUS_FAILURE);
963 // STEP 1. Decide number of fragments required to deliver this MSDU.
964 // The estimation here is not very accurate because difficult to
965 // take encryption overhead into consideration here. The result
966 // "NumberOfFrag" is then just used to pre-check if enough free
967 // TXD are available to hold this MSDU.
970 if (*pSrcBufVA & 0x01) // fragmentation not allowed on multicast & broadcast
972 else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))
973 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
974 else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED))
975 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
976 else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD))
977 NumberOfFrag = 1; // MIMO RATE overwhelms fragmentation
980 // The calculated "NumberOfFrag" is a rough estimation because of various
981 // encryption/encapsulation overhead not taken into consideration. This number is just
982 // used to make sure enough free TXD are available before fragmentation takes place.
983 // In case the actual required number of fragments of an NDIS packet
984 // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the
985 // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of
986 // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should
987 // rarely happen and the penalty is just like a TX RETRY fail. Affordable.
989 AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;
990 NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1;
991 // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size
992 if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0)
998 // Save fragment number to Ndis packet reserved field
999 RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
1002 // STEP 2. Check the requirement of RTS:
1003 // If multiple fragment required, RTS is required only for the first fragment
1004 // if the fragment size large than RTS threshold
1005 // For RT28xx, Let ASIC send RTS/CTS
1006 RTMP_SET_PACKET_RTS(pPacket, 0);
1007 RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate);
1010 // STEP 3. Traffic classification. outcome = <UserPriority, QueIdx>
1014 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
1017 UCHAR LlcSnapLen = 0, Byte0, Byte1;
1020 // get Ethernet protocol field
1021 Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
1022 if (Protocol <= 1500)
1024 // get Ethernet protocol field from LLC/SNAP
1025 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1028 Protocol = (USHORT)((Byte0 << 8) + Byte1);
1032 // always AC_BE for non-IP packet
1033 if (Protocol != 0x0800)
1037 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1040 // return AC_BE if packet is not IPv4
1041 if ((Byte0 & 0xf0) != 0x40)
1045 UserPriority = (Byte1 & 0xe0) >> 5;
1046 QueIdx = MapUserPriorityToAccessCategory[UserPriority];
1048 // TODO: have to check ACM bit. apply TSPEC if ACM is ON
1049 // TODO: downgrade UP & QueIdx before passing ACM
1050 if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx])
1058 RTMP_SET_PACKET_UP(pPacket, UserPriority);
1062 // Make sure SendTxWait queue resource won't be used by other threads
1063 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1064 if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE)
1066 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1067 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1069 return NDIS_STATUS_FAILURE;
1073 InsertTailQueue(&pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket));
1075 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1077 if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&&
1078 (pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE))
1080 if (((pEntry->TXBAbitmap & (1<<UserPriority)) == 0) &&
1081 ((pEntry->BADeclineBitmap & (1<<UserPriority)) == 0) &&
1082 (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
1083 // For IOT compatibility, if
1084 // 1. It is Ralink chip or
1085 // 2. It is OPEN or AES mode,
1086 // then BA session can be bulit.
1087 && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) ||
1088 (pEntry->WepStatus == Ndis802_11WEPDisabled || pEntry->WepStatus == Ndis802_11Encryption3Enabled))
1091 BAOriSessionSetUp(pAd, pEntry, 0, 0, 10, FALSE);
1095 pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed
1096 return NDIS_STATUS_SUCCESS;
1101 ========================================================================
1103 Routine Description:
1104 This subroutine will scan through releative ring descriptor to find
1105 out avaliable free ring descriptor and compare with request size.
1108 pAd Pointer to our adapter
1109 QueIdx Selected TX Ring
1112 NDIS_STATUS_FAILURE Not enough free descriptor
1113 NDIS_STATUS_SUCCESS Enough free descriptor
1115 IRQL = PASSIVE_LEVEL
1116 IRQL = DISPATCH_LEVEL
1120 ========================================================================
1122 NDIS_STATUS RTMPFreeTXDRequest(
1123 IN PRTMP_ADAPTER pAd,
1125 IN UCHAR NumberRequired,
1126 IN PUCHAR FreeNumberIs)
1128 ULONG FreeNumber = 0;
1129 NDIS_STATUS Status = NDIS_STATUS_FAILURE;
1138 if (pAd->TxRing[QueIdx].TxSwFreeIdx > pAd->TxRing[QueIdx].TxCpuIdx)
1139 FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx - pAd->TxRing[QueIdx].TxCpuIdx - 1;
1141 FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx + TX_RING_SIZE - pAd->TxRing[QueIdx].TxCpuIdx - 1;
1143 if (FreeNumber >= NumberRequired)
1144 Status = NDIS_STATUS_SUCCESS;
1148 if (pAd->MgmtRing.TxSwFreeIdx > pAd->MgmtRing.TxCpuIdx)
1149 FreeNumber = pAd->MgmtRing.TxSwFreeIdx - pAd->MgmtRing.TxCpuIdx - 1;
1151 FreeNumber = pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE - pAd->MgmtRing.TxCpuIdx - 1;
1153 if (FreeNumber >= NumberRequired)
1154 Status = NDIS_STATUS_SUCCESS;
1158 DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1161 *FreeNumberIs = (UCHAR)FreeNumber;
1168 VOID RTMPSendDisassociationFrame(
1169 IN PRTMP_ADAPTER pAd)
1173 VOID RTMPSendNullFrame(
1174 IN PRTMP_ADAPTER pAd,
1176 IN BOOLEAN bQosNull)
1178 UCHAR NullFrame[48];
1180 PHEADER_802_11 pHeader_802_11;
1182 // WPA 802.1x secured port control
1183 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1184 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1185 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1186 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1187 || (pAd->StaCfg.IEEE8021X == TRUE)
1189 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1194 NdisZeroMemory(NullFrame, 48);
1195 Length = sizeof(HEADER_802_11);
1197 pHeader_802_11 = (PHEADER_802_11) NullFrame;
1199 pHeader_802_11->FC.Type = BTYPE_DATA;
1200 pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
1201 pHeader_802_11->FC.ToDs = 1;
1202 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1203 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1204 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1206 if (pAd->CommonCfg.bAPSDForcePowerSave)
1208 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1212 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0;
1214 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
1217 pHeader_802_11->Sequence = pAd->Sequence;
1219 // Prepare QosNull function frame
1222 pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
1224 // copy QOS control bytes
1225 NullFrame[Length] = 0;
1226 NullFrame[Length+1] = 0;
1227 Length += 2;// if pad with 2 bytes for alignment, APSD will fail
1230 HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
1234 // IRQL = DISPATCH_LEVEL
1235 VOID RTMPSendRTSFrame(
1236 IN PRTMP_ADAPTER pAd,
1238 IN unsigned int NextMpduSize,
1241 IN USHORT AckDuration,
1249 // --------------------------------------------------------
1250 // FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM
1251 // Find the WPA key, either Group or Pairwise Key
1252 // LEAP + TKIP also use WPA key.
1253 // --------------------------------------------------------
1254 // Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst
1255 // In Cisco CCX 2.0 Leap Authentication
1256 // WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey
1257 // Instead of the SharedKey, SharedKey Length may be Zero.
1258 VOID STAFindCipherAlgorithm(
1259 IN PRTMP_ADAPTER pAd,
1262 NDIS_802_11_ENCRYPTION_STATUS Cipher; // To indicate cipher used for this packet
1263 UCHAR CipherAlg = CIPHER_NONE; // cipher alogrithm
1264 UCHAR KeyIdx = 0xff;
1266 PCIPHER_KEY pKey = NULL;
1268 pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
1272 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1273 Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast
1275 Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast
1277 if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
1279 ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128);
1281 // 4-way handshaking frame must be clear
1282 if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) &&
1283 (pAd->SharedKey[BSS0][0].KeyLen))
1285 CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1289 else if (Cipher == Ndis802_11Encryption1Enabled)
1291 KeyIdx = pAd->StaCfg.DefaultKeyId;
1293 else if ((Cipher == Ndis802_11Encryption2Enabled) ||
1294 (Cipher == Ndis802_11Encryption3Enabled))
1296 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast
1297 KeyIdx = pAd->StaCfg.DefaultKeyId;
1298 else if (pAd->SharedKey[BSS0][0].KeyLen)
1301 KeyIdx = pAd->StaCfg.DefaultKeyId;
1305 CipherAlg = CIPHER_NONE;
1306 else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
1307 CipherAlg = CIPHER_NONE;
1308 else if ( pAd->StaCfg.WpaSupplicantUP &&
1309 (Cipher == Ndis802_11Encryption1Enabled) &&
1310 (pAd->StaCfg.IEEE8021X == TRUE) &&
1311 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1312 CipherAlg = CIPHER_NONE;
1315 //Header_802_11.FC.Wep = 1;
1316 CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
1317 pKey = &pAd->SharedKey[BSS0][KeyIdx];
1321 pTxBlk->CipherAlg = CipherAlg;
1322 pTxBlk->pKey = pKey;
1326 VOID STABuildCommon802_11Header(
1327 IN PRTMP_ADAPTER pAd,
1330 HEADER_802_11 *pHeader_802_11;
1333 // MAKE A COMMON 802.11 HEADER
1336 // normal wlan header size : 24 octets
1337 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1339 pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1341 NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11));
1343 pHeader_802_11->FC.FrDs = 0;
1344 pHeader_802_11->FC.Type = BTYPE_DATA;
1345 pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA);
1347 if (pTxBlk->pMacEntry)
1349 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS))
1351 pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq;
1352 pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ;
1357 pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority];
1358 pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1364 pHeader_802_11->Sequence = pAd->Sequence;
1365 pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence
1368 pHeader_802_11->Frag = 0;
1370 pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1376 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1377 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1378 COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader);
1379 pHeader_802_11->FC.ToDs = 1;
1382 else if (ADHOC_ON(pAd))
1384 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1385 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1386 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1387 pHeader_802_11->FC.ToDs = 0;
1391 if (pTxBlk->CipherAlg != CIPHER_NONE)
1392 pHeader_802_11->FC.Wep = 1;
1394 // -----------------------------------------------------------------
1395 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1396 // -----------------------------------------------------------------
1397 if (pAd->CommonCfg.bAPSDForcePowerSave)
1398 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1400 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1403 VOID STABuildCache802_11Header(
1404 IN RTMP_ADAPTER *pAd,
1408 MAC_TABLE_ENTRY *pMacEntry;
1409 PHEADER_802_11 pHeader80211;
1411 pHeader80211 = (PHEADER_802_11)pHeader;
1412 pMacEntry = pTxBlk->pMacEntry;
1415 // Update the cached 802.11 HEADER
1418 // normal wlan header size : 24 octets
1419 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1422 pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1425 pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
1426 pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1429 // The addr3 of normal packet send from DS is Dest Mac address.
1431 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1433 COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader);
1436 // -----------------------------------------------------------------
1437 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1438 // -----------------------------------------------------------------
1439 if (pAd->CommonCfg.bAPSDForcePowerSave)
1440 pHeader80211->FC.PwrMgmt = PWR_SAVE;
1442 pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1445 static inline PUCHAR STA_Build_ARalink_Frame_Header(
1446 IN RTMP_ADAPTER *pAd,
1449 PUCHAR pHeaderBufPtr;
1450 HEADER_802_11 *pHeader_802_11;
1451 PNDIS_PACKET pNextPacket;
1453 PQUEUE_ENTRY pQEntry;
1455 STAFindCipherAlgorithm(pAd, pTxBlk);
1456 STABuildCommon802_11Header(pAd, pTxBlk);
1459 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1460 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1462 // steal "order" bit to mark "aggregation"
1463 pHeader_802_11->FC.Order = 1;
1465 // skip common header
1466 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1468 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1471 // build QOS Control bytes
1473 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1475 *(pHeaderBufPtr+1) = 0;
1477 pTxBlk->MpduHeaderLen += 2;
1480 // padding at front of LLC header. LLC header should at 4-bytes aligment.
1481 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1482 pHeaderBufPtr = (PCHAR)ROUND_UP(pHeaderBufPtr, 4);
1483 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1485 // For RA Aggregation,
1486 // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format
1487 pQEntry = pTxBlk->TxPacketList.Head;
1488 pNextPacket = QUEUE_ENTRY_TO_PKT(pQEntry);
1489 nextBufLen = GET_OS_PKT_LEN(pNextPacket);
1490 if (RTMP_GET_PACKET_VLAN(pNextPacket))
1491 nextBufLen -= LENGTH_802_1Q;
1493 *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff;
1494 *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8);
1497 pTxBlk->MpduHeaderLen += 2;
1499 return pHeaderBufPtr;
1503 static inline PUCHAR STA_Build_AMSDU_Frame_Header(
1504 IN RTMP_ADAPTER *pAd,
1507 PUCHAR pHeaderBufPtr;//, pSaveBufPtr;
1508 HEADER_802_11 *pHeader_802_11;
1511 STAFindCipherAlgorithm(pAd, pTxBlk);
1512 STABuildCommon802_11Header(pAd, pTxBlk);
1514 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1515 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1517 // skip common header
1518 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1521 // build QOS Control bytes
1523 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1528 *pHeaderBufPtr |= 0x80;
1530 *(pHeaderBufPtr+1) = 0;
1532 pTxBlk->MpduHeaderLen += 2;
1534 //pSaveBufPtr = pHeaderBufPtr;
1537 // padding at front of LLC header
1538 // LLC header should locate at 4-octets aligment
1540 // @@@ MpduHeaderLen excluding padding @@@
1542 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1543 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1544 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1546 return pHeaderBufPtr;
1551 VOID STA_AMPDU_Frame_Tx(
1552 IN PRTMP_ADAPTER pAd,
1555 HEADER_802_11 *pHeader_802_11;
1556 PUCHAR pHeaderBufPtr;
1558 MAC_TABLE_ENTRY *pMacEntry;
1560 PQUEUE_ENTRY pQEntry;
1564 while(pTxBlk->TxPacketList.Head)
1566 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1567 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1568 if ( RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1570 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1574 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1576 pMacEntry = pTxBlk->pMacEntry;
1577 if (pMacEntry->isCached)
1579 // NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!!
1580 NdisMoveMemory((PUCHAR)&pTxBlk->HeaderBuf[TXINFO_SIZE], (PUCHAR)&pMacEntry->CachedBuf[0], TXWI_SIZE + sizeof(HEADER_802_11));
1581 pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]);
1582 STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
1586 STAFindCipherAlgorithm(pAd, pTxBlk);
1587 STABuildCommon802_11Header(pAd, pTxBlk);
1589 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1593 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1595 // skip common header
1596 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1599 // build QOS Control bytes
1601 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1602 *(pHeaderBufPtr+1) = 0;
1604 pTxBlk->MpduHeaderLen += 2;
1608 // HTC control filed following QoS field
1610 if ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))
1612 if (pMacEntry->isCached == FALSE)
1615 pHeader_802_11->FC.Order = 1;
1617 NdisZeroMemory(pHeaderBufPtr, 4);
1618 *(pHeaderBufPtr+3) |= 0x80;
1621 pTxBlk->MpduHeaderLen += 4;
1624 //pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE;
1625 ASSERT(pTxBlk->MpduHeaderLen >= 24);
1627 // skip 802.3 header
1628 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1629 pTxBlk->SrcBufLen -= LENGTH_802_3;
1634 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1635 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1639 // padding at front of LLC header
1640 // LLC header should locate at 4-octets aligment
1642 // @@@ MpduHeaderLen excluding padding @@@
1644 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1645 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1646 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1651 // Insert LLC-SNAP encapsulation - 8 octets
1653 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1654 if (pTxBlk->pExtraLlcSnapEncap)
1656 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1658 // get 2 octets (TypeofLen)
1659 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1661 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1666 if (pMacEntry->isCached)
1668 RTMPWriteTxWI_Cache(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1672 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1674 NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf));
1675 NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE])));
1676 pMacEntry->isCached = TRUE;
1679 // calculate Transmitted AMPDU count and ByteCount
1681 pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++;
1682 pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen;
1685 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1687 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1692 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
1693 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1695 pAd->RalinkCounters.KickTxCount++;
1696 pAd->RalinkCounters.OneSecTxDoneCount++;
1702 VOID STA_AMSDU_Frame_Tx(
1703 IN PRTMP_ADAPTER pAd,
1706 PUCHAR pHeaderBufPtr;
1708 USHORT subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding.
1709 USHORT totalMPDUSize=0;
1710 UCHAR *subFrameHeader;
1712 USHORT FirstTx = 0, LastTxIdx = 0;
1715 PQUEUE_ENTRY pQEntry;
1720 ASSERT((pTxBlk->TxPacketList.Number > 1));
1722 while(pTxBlk->TxPacketList.Head)
1724 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1725 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1726 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1728 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1732 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1734 // skip 802.3 header
1735 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1736 pTxBlk->SrcBufLen -= LENGTH_802_3;
1741 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1742 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1747 pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
1749 // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled.
1750 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1754 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
1755 padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen);
1756 NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD);
1757 pHeaderBufPtr += padding;
1758 pTxBlk->MpduHeaderLen = padding;
1763 // DA(6)+SA(6)+Length(2) + LLC/SNAP Encap
1765 subFrameHeader = pHeaderBufPtr;
1766 subFramePayloadLen = pTxBlk->SrcBufLen;
1768 NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
1771 pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
1772 pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
1776 // Insert LLC-SNAP encapsulation - 8 octets
1778 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1780 subFramePayloadLen = pTxBlk->SrcBufLen;
1782 if (pTxBlk->pExtraLlcSnapEncap)
1784 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1786 // get 2 octets (TypeofLen)
1787 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1789 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1790 subFramePayloadLen += LENGTH_802_1_H;
1793 // update subFrame Length field
1794 subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
1795 subFrameHeader[13] = subFramePayloadLen & 0xFF;
1797 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1800 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1802 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1806 pAd->RalinkCounters.KickTxCount++;
1807 pAd->RalinkCounters.OneSecTxDoneCount++;
1809 // calculate Transmitted AMSDU Count and ByteCount
1811 pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++;
1812 pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize;
1817 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
1818 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
1823 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
1824 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1827 VOID STA_Legacy_Frame_Tx(
1828 IN PRTMP_ADAPTER pAd,
1831 HEADER_802_11 *pHeader_802_11;
1832 PUCHAR pHeaderBufPtr;
1835 PQUEUE_ENTRY pQEntry;
1840 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1841 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1842 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1844 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1848 if (pTxBlk->TxFrameType == TX_MCAST_FRAME)
1850 INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
1853 if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
1854 TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
1856 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
1858 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1860 if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
1861 pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
1863 STAFindCipherAlgorithm(pAd, pTxBlk);
1864 STABuildCommon802_11Header(pAd, pTxBlk);
1867 // skip 802.3 header
1868 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1869 pTxBlk->SrcBufLen -= LENGTH_802_3;
1874 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1875 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1878 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1879 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1881 // skip common header
1882 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1884 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1887 // build QOS Control bytes
1889 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1890 *(pHeaderBufPtr+1) = 0;
1892 pTxBlk->MpduHeaderLen += 2;
1895 // The remaining content of MPDU header should locate at 4-octets aligment
1896 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1897 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1898 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1903 // Insert LLC-SNAP encapsulation - 8 octets
1906 // if original Ethernet frame contains no LLC/SNAP,
1907 // then an extra LLC/SNAP encap is required
1909 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
1910 if (pTxBlk->pExtraLlcSnapEncap)
1914 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1917 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
1918 // get 2 octets (TypeofLen)
1919 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
1921 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1928 // use Wcid as Key Index
1931 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1933 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1935 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1937 pAd->RalinkCounters.KickTxCount++;
1938 pAd->RalinkCounters.OneSecTxDoneCount++;
1943 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
1944 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1948 VOID STA_ARalink_Frame_Tx(
1949 IN PRTMP_ADAPTER pAd,
1952 PUCHAR pHeaderBufPtr;
1954 USHORT totalMPDUSize=0;
1955 USHORT FirstTx, LastTxIdx;
1958 PQUEUE_ENTRY pQEntry;
1963 ASSERT((pTxBlk->TxPacketList.Number== 2));
1966 FirstTx = LastTxIdx = 0; // Is it ok init they as 0?
1967 while(pTxBlk->TxPacketList.Head)
1969 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1970 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1972 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1974 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1978 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1980 // skip 802.3 header
1981 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1982 pTxBlk->SrcBufLen -= LENGTH_802_3;
1987 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1988 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1992 { // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header
1994 pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
1996 // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount
1997 // will be updated after final frame was handled.
1998 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2002 // Insert LLC-SNAP encapsulation - 8 octets
2004 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
2006 if (pTxBlk->pExtraLlcSnapEncap)
2008 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2010 // get 2 octets (TypeofLen)
2011 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2013 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2017 { // For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0.
2019 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
2020 pTxBlk->MpduHeaderLen = 0;
2022 // A-Ralink sub-sequent frame header is the same as 802.3 header.
2023 // DA(6)+SA(6)+FrameType(2)
2024 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12);
2025 pHeaderBufPtr += 12;
2026 // get 2 octets (TypeofLen)
2027 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2029 pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD;
2032 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2034 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2036 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2038 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2042 pAd->RalinkCounters.OneSecTxAggregationCount++;
2043 pAd->RalinkCounters.KickTxCount++;
2044 pAd->RalinkCounters.OneSecTxDoneCount++;
2048 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2049 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2054 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2055 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2060 VOID STA_Fragment_Frame_Tx(
2061 IN RTMP_ADAPTER *pAd,
2064 HEADER_802_11 *pHeader_802_11;
2065 PUCHAR pHeaderBufPtr;
2068 PACKET_INFO PacketInfo;
2069 USHORT EncryptionOverhead = 0;
2070 UINT32 FreeMpduSize, SrcRemainingBytes;
2074 PQUEUE_ENTRY pQEntry;
2079 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2080 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2081 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2083 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2087 ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag));
2088 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2090 STAFindCipherAlgorithm(pAd, pTxBlk);
2091 STABuildCommon802_11Header(pAd, pTxBlk);
2093 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2095 pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket);
2096 if (pTxBlk->pPacket == NULL)
2098 RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
2101 // skip 802.3 header
2102 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2103 pTxBlk->SrcBufLen -= LENGTH_802_3;
2109 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2110 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2113 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2114 pHeader_802_11 = (HEADER_802_11 *)pHeaderBufPtr;
2117 // skip common header
2118 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2120 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2123 // build QOS Control bytes
2125 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2127 *(pHeaderBufPtr+1) = 0;
2129 pTxBlk->MpduHeaderLen += 2;
2133 // padding at front of LLC header
2134 // LLC header should locate at 4-octets aligment
2136 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2137 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2138 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2143 // Insert LLC-SNAP encapsulation - 8 octets
2146 // if original Ethernet frame contains no LLC/SNAP,
2147 // then an extra LLC/SNAP encap is required
2149 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2150 if (pTxBlk->pExtraLlcSnapEncap)
2154 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2157 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2158 // get 2 octets (TypeofLen)
2159 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2161 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2165 // If TKIP is used and fragmentation is required. Driver has to
2166 // append TKIP MIC at tail of the scatter buffer
2167 // MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC
2168 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2171 // NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust
2172 // to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress.
2173 NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8);
2174 //skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8);
2175 pTxBlk->SrcBufLen += 8;
2176 pTxBlk->TotalFrameLen += 8;
2177 pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC;
2181 // calcuate the overhead bytes that encryption algorithm may add. This
2182 // affects the calculate of "duration" field
2184 if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128))
2185 EncryptionOverhead = 8; //WEP: IV[4] + ICV[4];
2186 else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC)
2187 EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength
2188 else if (pTxBlk->CipherAlg == CIPHER_TKIP)
2189 EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8]
2190 else if (pTxBlk->CipherAlg == CIPHER_AES)
2191 EncryptionOverhead = 16; // AES: IV[4] + EIV[4] + MIC[8]
2193 EncryptionOverhead = 0;
2195 // decide how much time an ACK/CTS frame will consume in the air
2196 AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14);
2198 // Init the total payload length of this frame.
2199 SrcRemainingBytes = pTxBlk->SrcBufLen;
2201 pTxBlk->TotalFragNum = 0xff;
2205 FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC;
2207 FreeMpduSize -= pTxBlk->MpduHeaderLen;
2209 if (SrcRemainingBytes <= FreeMpduSize)
2210 { // this is the last or only fragment
2212 pTxBlk->SrcBufLen = SrcRemainingBytes;
2214 pHeader_802_11->FC.MoreFrag = 0;
2215 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + AckDuration;
2217 // Indicate the lower layer that this's the last fragment.
2218 pTxBlk->TotalFragNum = fragNum;
2221 { // more fragment is required
2223 pTxBlk->SrcBufLen = FreeMpduSize;
2225 NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), ((UINT)pAd->CommonCfg.FragmentThreshold));
2226 pHeader_802_11->FC.MoreFrag = 1;
2227 pHeader_802_11->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead);
2231 pTxBlk->FrameGap = IFS_HTTXOP;
2233 pTxBlk->FrameGap = IFS_SIFS;
2235 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2237 HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber);
2239 pAd->RalinkCounters.KickTxCount++;
2240 pAd->RalinkCounters.OneSecTxDoneCount++;
2242 // Update the frame number, remaining size of the NDIS packet payload.
2244 // space for 802.11 header.
2245 if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap)
2246 pTxBlk->MpduHeaderLen -= LENGTH_802_1_H;
2249 SrcRemainingBytes -= pTxBlk->SrcBufLen;
2250 pTxBlk->pSrcBufData += pTxBlk->SrcBufLen;
2252 pHeader_802_11->Frag++; // increase Frag #
2254 }while(SrcRemainingBytes > 0);
2259 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2263 #define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \
2264 while(_pTxBlk->TxPacketList.Head) \
2266 _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList); \
2267 RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \
2272 ========================================================================
2274 Routine Description:
2275 Copy frame from waiting queue into relative ring buffer and set
2276 appropriate ASIC register to kick hardware encryption before really
2280 pAd Pointer to our adapter
2281 PNDIS_PACKET Pointer to outgoing Ndis frame
2282 NumberOfFrag Number of fragment required
2287 IRQL = DISPATCH_LEVEL
2291 ========================================================================
2293 NDIS_STATUS STAHardTransmit(
2294 IN PRTMP_ADAPTER pAd,
2298 NDIS_PACKET *pPacket;
2299 PQUEUE_ENTRY pQEntry;
2301 // ---------------------------------------------
2302 // STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION.
2303 // ---------------------------------------------
2305 ASSERT(pTxBlk->TxPacketList.Number);
2306 if (pTxBlk->TxPacketList.Head == NULL)
2308 DBGPRINT(RT_DEBUG_ERROR, ("pTxBlk->TotalFrameNum == %ld!\n", pTxBlk->TxPacketList.Number));
2309 return NDIS_STATUS_FAILURE;
2312 pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head);
2314 // ------------------------------------------------------------------
2315 // STEP 1. WAKE UP PHY
2316 // outgoing frame always wakeup PHY to prevent frame lost and
2317 // turn off PSM bit to improve performance
2318 // ------------------------------------------------------------------
2319 // not to change PSM bit, just send this frame out?
2320 if ((pAd->StaCfg.Psm == PWR_SAVE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2322 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicForceWakeup At HardTx\n"));
2323 AsicForceWakeup(pAd, FROM_TX);
2326 // It should not change PSM bit, when APSD turn on.
2327 if ((!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE))
2328 || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
2329 || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket)))
2331 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
2332 (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeFast_PSP))
2333 MlmeSetPsmBit(pAd, PWR_ACTIVE);
2336 switch (pTxBlk->TxFrameType)
2338 case TX_AMPDU_FRAME:
2339 STA_AMPDU_Frame_Tx(pAd, pTxBlk);
2341 case TX_AMSDU_FRAME:
2342 STA_AMSDU_Frame_Tx(pAd, pTxBlk);
2344 case TX_LEGACY_FRAME:
2345 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2347 case TX_MCAST_FRAME:
2348 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2350 case TX_RALINK_FRAME:
2351 STA_ARalink_Frame_Tx(pAd, pTxBlk);
2354 STA_Fragment_Frame_Tx(pAd, pTxBlk);
2358 // It should not happened!
2359 DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!! It should not happen!\n"));
2360 while(pTxBlk->TxPacketList.Number)
2362 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2363 pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2365 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2371 return (NDIS_STATUS_SUCCESS);
2375 ULONG HashBytesPolynomial(UCHAR *value, unsigned int len)
2377 unsigned char *word = value;
2378 unsigned int ret = 0;
2381 for(i=0; i < len; i++)
2384 ret ^=(unsigned int) (word[i]) << mod;
2385 ret ^=(unsigned int) (word[i]) >> (32 - mod);
2390 VOID Sta_Announce_or_Forward_802_3_Packet(
2391 IN PRTMP_ADAPTER pAd,
2392 IN PNDIS_PACKET pPacket,
2393 IN UCHAR FromWhichBSSID)
2398 announce_802_3_packet(pAd, pPacket);
2403 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);