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 -------- ---------- ----------------------------------------------
37 #include "../rt_config.h"
38 #include <linux/kernel.h>
40 void STARxEAPOLFrameIndicate(struct rt_rtmp_adapter *pAd,
41 struct rt_mac_table_entry *pEntry,
42 struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
44 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
45 struct rt_rxwi * pRxWI = pRxBlk->pRxWI;
48 if (pAd->StaCfg.WpaSupplicantUP) {
49 /* All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon) */
50 /* TBD : process fragmented EAPol frames */
52 /* In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable */
53 if (pAd->StaCfg.IEEE8021X == TRUE &&
55 WpaCheckEapCode(pAd, pRxBlk->pData,
62 DBGPRINT_RAW(RT_DEBUG_TRACE,
63 ("Receive EAP-SUCCESS Packet\n"));
64 /*pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; */
65 STA_PORT_SECURED(pAd);
67 if (pAd->StaCfg.IEEE8021x_required_keys ==
69 idx = pAd->StaCfg.DesireSharedKeyId;
71 pAd->StaCfg.DesireSharedKey[idx].
74 pAd->StaCfg.DesireSharedKey[idx].
77 if (pAd->StaCfg.DesireSharedKey[idx].
80 struct rt_mac_table_entry *pEntry =
84 /* Set key material and cipherAlg to Asic */
85 AsicAddSharedKeyEntry(pAd, BSS0,
91 /* Assign group key info */
92 RTMPAddWcidAttributeEntry(pAd,
98 /* Assign pairwise key info */
99 RTMPAddWcidAttributeEntry(pAd,
105 pAd->IndicateMediaState =
106 NdisMediaStateConnected;
109 #endif /* RTMP_MAC_PCI // */
113 (struct rt_ndis_802_11_wep)
117 struct rt_ndis_802_11_wep keyinfo;
122 NdisZeroMemory(&WepKey,
126 DesireSharedKey[idx].KeyLen;
128 NdisMoveMemory(WepKey.keyinfo.
137 WepKey.keyinfo.KeyIndex =
139 WepKey.keyinfo.KeyLength = len;
140 pAd->SharedKey[BSS0][idx].
142 (u8)(len <= 5 ? 5 : 13);
144 pAd->IndicateMediaState =
145 NdisMediaStateConnected;
148 /* need to enqueue cmd to thread */
149 RTUSBEnqueueCmdFromNdis(pAd,
158 #endif /* RTMP_MAC_USB // */
159 /* For Preventing ShardKey Table is cleared by remove key procedure. */
160 pAd->SharedKey[BSS0][idx].
161 CipherAlg = CipherAlg;
162 pAd->SharedKey[BSS0][idx].
165 DesireSharedKey[idx].KeyLen;
179 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
183 /* Special DATA frame that has to pass to MLME */
184 /* 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process */
185 /* 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process */
187 pTmpBuf = pRxBlk->pData - LENGTH_802_11;
188 NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11);
189 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID,
192 LENGTH_802_11, pRxWI->RSSI0,
193 pRxWI->RSSI1, pRxWI->RSSI2,
195 DBGPRINT_RAW(RT_DEBUG_TRACE,
196 ("report EAPOL/AIRONET DATA to MLME (len=%d) !\n",
201 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
206 void STARxDataFrameAnnounce(struct rt_rtmp_adapter *pAd,
207 struct rt_mac_table_entry *pEntry,
208 struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
212 if (!RTMPCheckWPAframe
213 (pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID)) {
216 /* drop all non-EAP DATA frame before */
217 /* this client's Port-Access-Control is secured */
218 if (pRxBlk->pHeader->FC.Wep) {
219 /* unsupported cipher suite */
220 if (pAd->StaCfg.WepStatus ==
221 Ndis802_11EncryptionDisabled) {
223 RELEASE_NDIS_PACKET(pAd,
225 NDIS_STATUS_FAILURE);
229 /* encryption in-use but receive a non-EAPOL clear text frame, drop it */
230 if ((pAd->StaCfg.WepStatus !=
231 Ndis802_11EncryptionDisabled)
232 && (pAd->StaCfg.PortSecured ==
233 WPA_802_1X_PORT_NOT_SECURED)) {
235 RELEASE_NDIS_PACKET(pAd,
237 NDIS_STATUS_FAILURE);
242 RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP);
243 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK)) {
244 /* Normal legacy, AMPDU or AMSDU */
245 CmmRxnonRalinkFrameIndicate(pAd, pRxBlk,
250 CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk,
254 RX_BLK_SET_FLAG(pRxBlk, fRX_EAP);
256 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU)
257 && (pAd->CommonCfg.bDisableReordering == 0)) {
258 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
260 /* Determin the destination of the EAP frame */
261 /* to WPA state machine or upper layer */
262 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk,
268 /* For TKIP frame, calculate the MIC value */
269 BOOLEAN STACheckTkipMICValue(struct rt_rtmp_adapter *pAd,
270 struct rt_mac_table_entry *pEntry, struct rt_rx_blk *pRxBlk)
272 struct rt_header_802_11 * pHeader = pRxBlk->pHeader;
273 u8 *pData = pRxBlk->pData;
274 u16 DataSize = pRxBlk->DataSize;
275 u8 UserPriority = pRxBlk->UserPriority;
276 struct rt_cipher_key *pWpaKey;
279 pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex];
281 pDA = pHeader->Addr1;
282 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA)) {
283 pSA = pHeader->Addr3;
285 pSA = pHeader->Addr2;
288 if (RTMPTkipCompareMICValue(pAd,
293 UserPriority, DataSize) == FALSE) {
294 DBGPRINT_RAW(RT_DEBUG_ERROR, ("Rx MIC Value error 2\n"));
296 if (pAd->StaCfg.WpaSupplicantUP) {
297 WpaSendMicFailureToWpaSupplicant(pAd,
299 PAIRWISEKEY) ? TRUE :
302 RTMPReportMicError(pAd, pWpaKey);
306 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
307 NDIS_STATUS_FAILURE);
315 /* All Rx routines use struct rt_rx_blk structure to hande rx events */
316 /* It is very important to build pRxBlk attributes */
317 /* 1. pHeader pointer to 802.11 Header */
318 /* 2. pData pointer to payload including LLC (just skip Header) */
319 /* 3. set payload size including LLC to DataSize */
320 /* 4. set some flags with RX_BLK_SET_FLAG() */
322 void STAHandleRxDataFrame(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk)
324 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
325 struct rt_rxwi * pRxWI = pRxBlk->pRxWI;
326 struct rt_header_802_11 * pHeader = pRxBlk->pHeader;
327 void *pRxPacket = pRxBlk->pRxPacket;
328 BOOLEAN bFragment = FALSE;
329 struct rt_mac_table_entry *pEntry = NULL;
330 u8 FromWhichBSSID = BSS0;
334 /* before LINK UP, all DATA frames are rejected */
335 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) {
337 RELEASE_NDIS_PACKET(pAd, pRxPacket,
338 NDIS_STATUS_FAILURE);
341 /* Drop not my BSS frames */
342 if (pRxD->MyBss == 0) {
345 RELEASE_NDIS_PACKET(pAd, pRxPacket,
346 NDIS_STATUS_FAILURE);
351 pAd->RalinkCounters.RxCountSinceLastNULL++;
352 if (pAd->CommonCfg.bAPSDCapable
353 && pAd->CommonCfg.APEdcaParm.bAPSDCapable
354 && (pHeader->FC.SubType & 0x08)) {
356 DBGPRINT(RT_DEBUG_INFO, ("bAPSDCapable\n"));
359 pData = (u8 *)pHeader + LENGTH_802_11;
360 if ((*pData >> 4) & 0x01) {
361 DBGPRINT(RT_DEBUG_INFO,
362 ("RxDone- Rcv EOSP frame, driver may fall into sleep\n"));
363 pAd->CommonCfg.bInServicePeriod = FALSE;
365 /* Force driver to fall into sleep mode when rcv EOSP frame */
366 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) {
367 u16 TbttNumToNextWakeUp;
369 pAd->StaCfg.DtimPeriod;
372 NdisGetSystemUpTime(&Now);
377 pAd->CommonCfg.BeaconPeriod;
379 TbttNumToNextWakeUp =
380 pAd->StaCfg.DefaultListenCount;
381 if (OPSTATUS_TEST_FLAG
382 (pAd, fOP_STATUS_RECEIVE_DTIM)
383 && (TbttNumToNextWakeUp > NextDtim))
384 TbttNumToNextWakeUp = NextDtim;
386 RTMP_SET_PSM_BIT(pAd, PWR_SAVE);
387 /* if WMM-APSD is failed, try to disable following line */
388 AsicSleepThenAutoWakeup(pAd,
389 TbttNumToNextWakeUp);
393 if ((pHeader->FC.MoreData)
394 && (pAd->CommonCfg.bInServicePeriod)) {
395 DBGPRINT(RT_DEBUG_TRACE,
396 ("Sending another trigger frame when More Data bit is set to 1\n"));
399 /* Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame */
400 if ((pHeader->FC.SubType & 0x04)) /* bit 2 : no DATA */
403 RELEASE_NDIS_PACKET(pAd, pRxPacket,
404 NDIS_STATUS_FAILURE);
407 /* Drop not my BSS frame (we can not only check the MyBss bit in RxD) */
410 /* Infrastructure mode, check address 2 for BSSID */
412 (&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6)) {
413 /* Receive frame not my BSSID */
415 RELEASE_NDIS_PACKET(pAd, pRxPacket,
416 NDIS_STATUS_FAILURE);
419 } else /* Ad-Hoc mode or Not associated */
421 /* Ad-Hoc mode, check address 3 for BSSID */
423 (&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6)) {
424 /* Receive frame not my BSSID */
426 RELEASE_NDIS_PACKET(pAd, pRxPacket,
427 NDIS_STATUS_FAILURE);
435 if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE) {
436 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
438 /* 1. release packet if infra mode */
439 /* 2. new a pEntry if ad-hoc mode */
440 RELEASE_NDIS_PACKET(pAd, pRxPacket,
441 NDIS_STATUS_FAILURE);
445 /* infra or ad-hoc */
447 RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA);
448 ASSERT(pRxWI->WirelessCliID == BSSID_WCID);
450 /* check Atheros Client */
451 if ((pEntry->bIAmBadAtheros == FALSE) && (pRxD->AMPDU == 1)
452 && (pHeader->FC.Retry)) {
453 pEntry->bIAmBadAtheros = TRUE;
454 pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE;
455 pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE;
456 if (!STA_AES_ON(pAd)) {
457 AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE,
463 pRxBlk->pData = (u8 *) pHeader;
466 /* update RxBlk->pData, DataSize */
467 /* 802.11 Header, QOS, HTC, Hw Padding */
470 /* 1. skip 802.11 HEADER */
472 pRxBlk->pData += LENGTH_802_11;
473 pRxBlk->DataSize -= LENGTH_802_11;
477 if (pHeader->FC.SubType & 0x08) {
478 RX_BLK_SET_FLAG(pRxBlk, fRX_QOS);
479 UserPriority = *(pRxBlk->pData) & 0x0f;
480 /* bit 7 in QoS Control field signals the HT A-MSDU format */
481 if ((*pRxBlk->pData) & 0x80) {
482 RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU);
484 /* skip QOS contorl field */
486 pRxBlk->DataSize -= 2;
488 pRxBlk->UserPriority = UserPriority;
490 /* check if need to resend PS Poll when received packet with MoreData = 1 */
491 if ((pAd->StaCfg.Psm == PWR_SAVE) && (pHeader->FC.MoreData == 1)) {
492 if ((((UserPriority == 0) || (UserPriority == 3)) &&
493 pAd->CommonCfg.bAPSDAC_BE == 0) ||
494 (((UserPriority == 1) || (UserPriority == 2)) &&
495 pAd->CommonCfg.bAPSDAC_BK == 0) ||
496 (((UserPriority == 4) || (UserPriority == 5)) &&
497 pAd->CommonCfg.bAPSDAC_VI == 0) ||
498 (((UserPriority == 6) || (UserPriority == 7)) &&
499 pAd->CommonCfg.bAPSDAC_VO == 0)) {
500 /* non-UAPSD delivery-enabled AC */
501 RTMP_PS_POLL_ENQUEUE(pAd);
504 /* 3. Order bit: A-Ralink or HTC+ */
505 if (pHeader->FC.Order) {
506 #ifdef AGGREGATION_SUPPORT
507 if ((pRxWI->PHYMODE <= MODE_OFDM)
508 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)))
510 RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK);
512 #endif /* AGGREGATION_SUPPORT // */
514 RX_BLK_SET_FLAG(pRxBlk, fRX_HTC);
515 /* skip HTC contorl field */
517 pRxBlk->DataSize -= 4;
520 /* 4. skip HW padding */
522 /* just move pData pointer */
523 /* because DataSize excluding HW padding */
524 RX_BLK_SET_FLAG(pRxBlk, fRX_PAD);
529 RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU);
532 /* Case I Process Broadcast & Multicast data frame */
534 if (pRxD->Bcast || pRxD->Mcast) {
535 INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount);
537 /* Drop Mcast/Bcast frame with fragment bit on */
538 if (pHeader->FC.MoreFrag) {
540 RELEASE_NDIS_PACKET(pAd, pRxPacket,
541 NDIS_STATUS_FAILURE);
544 /* Filter out Bcast frame which AP relayed for us */
546 && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress)) {
548 RELEASE_NDIS_PACKET(pAd, pRxPacket,
549 NDIS_STATUS_FAILURE);
553 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
555 } else if (pRxD->U2M) {
557 (u16)((pRxWI->MCS) + (pRxWI->BW << 7) +
558 (pRxWI->ShortGI << 8) + (pRxWI->PHYMODE << 14));
561 pEntry = MacTableLookup(pAd, pHeader->Addr2);
563 Update_Rssi_Sample(pAd, &pEntry->RssiSample,
567 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
569 pAd->StaCfg.LastSNR0 = (u8)(pRxWI->SNR0);
570 pAd->StaCfg.LastSNR1 = (u8)(pRxWI->SNR1);
572 pAd->RalinkCounters.OneSecRxOkDataCnt++;
574 if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0))) {
575 /* re-assemble the fragmented packets */
576 /* return complete frame (pRxPacket) or NULL */
578 pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk);
582 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
584 /* process complete frame */
585 if (bFragment && (pRxD->Decrypted)
586 && (pEntry->WepStatus ==
587 Ndis802_11Encryption2Enabled)) {
588 /* Minus MIC length */
589 pRxBlk->DataSize -= 8;
591 /* For TKIP frame, calculate the MIC value */
592 if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) ==
598 STARxDataFrameAnnounce(pAd, pEntry, pRxBlk,
603 /* because RTMPDeFragmentDataFrame() will release rx packet, */
604 /* if packet is fragmented */
611 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
614 void STAHandleRxMgmtFrame(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk)
616 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
617 struct rt_rxwi * pRxWI = pRxBlk->pRxWI;
618 struct rt_header_802_11 * pHeader = pRxBlk->pHeader;
619 void *pRxPacket = pRxBlk->pRxPacket;
623 /* check if need to resend PS Poll when received packet with MoreData = 1 */
624 if ((pAd->StaCfg.Psm == PWR_SAVE)
625 && (pHeader->FC.MoreData == 1)) {
626 /* for UAPSD, all management frames will be VO priority */
627 if (pAd->CommonCfg.bAPSDAC_VO == 0) {
628 /* non-UAPSD delivery-enabled AC */
629 RTMP_PS_POLL_ENQUEUE(pAd);
633 /* TODO: if MoreData == 0, station can go to sleep */
635 /* We should collect RSSI not only U2M data but also my beacon */
636 if ((pHeader->FC.SubType == SUBTYPE_BEACON)
637 && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2))
638 && (pAd->RxAnt.EvaluatePeriod == 0)) {
639 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
641 pAd->StaCfg.LastSNR0 = (u8)(pRxWI->SNR0);
642 pAd->StaCfg.LastSNR1 = (u8)(pRxWI->SNR1);
645 /* First check the size, it MUST not exceed the mlme queue size */
646 if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE) {
647 DBGPRINT_ERR(("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount));
651 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader,
652 pRxWI->MPDUtotalByteCount,
653 pRxWI->RSSI0, pRxWI->RSSI1,
654 pRxWI->RSSI2, pRxD->PlcpSignal);
657 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
660 void STAHandleRxControlFrame(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk)
662 struct rt_rxwi * pRxWI = pRxBlk->pRxWI;
663 struct rt_header_802_11 * pHeader = pRxBlk->pHeader;
664 void *pRxPacket = pRxBlk->pRxPacket;
666 switch (pHeader->FC.SubType) {
667 case SUBTYPE_BLOCK_ACK_REQ:
669 CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID,
670 (pRxWI->MPDUtotalByteCount),
671 (struct rt_frame_ba_req *) pHeader);
674 case SUBTYPE_BLOCK_ACK:
680 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
684 ========================================================================
687 Process RxDone interrupt, running in DPC level
690 pAd Pointer to our adapter
695 IRQL = DISPATCH_LEVEL
698 This routine has to maintain Rx ring read pointer.
699 Need to consider QOS DATA format when converting to 802.3
700 ========================================================================
702 BOOLEAN STARxDoneInterruptHandle(struct rt_rtmp_adapter *pAd, IN BOOLEAN argc)
705 u32 RxProcessed, RxPending;
706 BOOLEAN bReschedule = FALSE;
707 PRT28XX_RXD_STRUC pRxD;
709 struct rt_rxwi * pRxWI;
711 struct rt_header_802_11 * pHeader;
712 struct rt_rx_blk RxCell;
714 RxProcessed = RxPending = 0;
716 /* process whole rx ring */
719 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF |
720 fRTMP_ADAPTER_RESET_IN_PROGRESS |
721 fRTMP_ADAPTER_HALT_IN_PROGRESS |
722 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
723 !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) {
727 if (RxProcessed++ > MAX_RX_PROCESS_CNT) {
728 /* need to reschedule rx handle */
732 #endif /* RTMP_MAC_PCI // */
734 RxProcessed++; /* test */
736 /* 1. allocate a new data packet into rx ring to replace received packet */
737 /* then processing the received packet */
738 /* 2. the callee must take charge of release of packet */
739 /* 3. As far as driver is concerned , */
740 /* the rx packet must */
741 /* a. be indicated to upper layer or */
742 /* b. be released if it is discarded */
744 GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule,
746 if (pRxPacket == NULL) {
747 /* no more packet to process */
750 /* get rx ring descriptor */
751 pRxD = &(RxCell.RxD);
752 /* get rx data buffer */
753 pData = GET_OS_PKT_DATAPTR(pRxPacket);
754 pRxWI = (struct rt_rxwi *) pData;
755 pHeader = (struct rt_header_802_11 *) (pData + RXWI_SIZE);
758 RxCell.pRxWI = pRxWI;
759 RxCell.pHeader = pHeader;
760 RxCell.pRxPacket = pRxPacket;
761 RxCell.pData = (u8 *) pHeader;
762 RxCell.DataSize = pRxWI->MPDUtotalByteCount;
765 /* Increase Total receive byte counter after real data received no mater any error or not */
766 pAd->RalinkCounters.ReceivedByteCount +=
767 pRxWI->MPDUtotalByteCount;
768 pAd->RalinkCounters.OneSecReceivedByteCount +=
769 pRxWI->MPDUtotalByteCount;
770 pAd->RalinkCounters.RxCount++;
772 INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount);
774 if (pRxWI->MPDUtotalByteCount < 14)
775 Status = NDIS_STATUS_FAILURE;
777 if (MONITOR_ON(pAd)) {
778 send_monitor_packets(pAd, &RxCell);
782 /* STARxDoneInterruptHandle() is called in rtusb_bulk.c */
784 /* Check for all RxD errors */
785 Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD);
787 /* Handle the received frame */
788 if (Status == NDIS_STATUS_SUCCESS) {
789 switch (pHeader->FC.Type) {
790 /* CASE I, receive a DATA frame */
793 /* process DATA frame */
794 STAHandleRxDataFrame(pAd, &RxCell);
797 /* CASE II, receive a MGMT frame */
800 STAHandleRxMgmtFrame(pAd, &RxCell);
803 /* CASE III. receive a CNTL frame */
806 STAHandleRxControlFrame(pAd, &RxCell);
809 /* discard other type */
811 RELEASE_NDIS_PACKET(pAd, pRxPacket,
812 NDIS_STATUS_FAILURE);
816 pAd->Counters8023.RxErrors++;
817 /* discard this frame */
818 RELEASE_NDIS_PACKET(pAd, pRxPacket,
819 NDIS_STATUS_FAILURE);
827 ========================================================================
831 pAd Pointer to our adapter
833 IRQL = DISPATCH_LEVEL
835 ========================================================================
837 void RTMPHandleTwakeupInterrupt(struct rt_rtmp_adapter *pAd)
839 AsicForceWakeup(pAd, FALSE);
843 ========================================================================
845 Early checking and OS-depened parsing for Tx packet send to our STA driver.
848 void * MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd.
849 void ** ppPacketArray The packet array need to do transmission.
850 u32 NumberOfPackets Number of packet in packet array.
856 This function do early checking and classification for send-out packet.
857 You only can put OS-depened & STA related code in here.
858 ========================================================================
860 void STASendPackets(void *MiniportAdapterContext,
861 void **ppPacketArray, u32 NumberOfPackets)
864 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)MiniportAdapterContext;
866 BOOLEAN allowToSend = FALSE;
868 for (Index = 0; Index < NumberOfPackets; Index++) {
869 pPacket = ppPacketArray[Index];
872 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)
873 || RTMP_TEST_FLAG(pAd,
874 fRTMP_ADAPTER_HALT_IN_PROGRESS)
875 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) {
876 /* Drop send request since hardware is in reset state */
878 } else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd)) {
879 /* Drop send request since there are no physical connection yet */
882 /* Record that orignal packet source is from NDIS layer,so that */
883 /* later on driver knows how to release this NDIS PACKET */
884 RTMP_SET_PACKET_WCID(pPacket, 0); /* this field is useless when in STA mode */
885 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
886 NDIS_SET_PACKET_STATUS(pPacket,
887 NDIS_STATUS_PENDING);
888 pAd->RalinkCounters.PendingNdisPacketCount++;
894 if (allowToSend == TRUE)
895 STASendPacket(pAd, pPacket);
897 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
900 /* Dequeue outgoing frames from TxSwQueue[] and process it */
901 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
906 ========================================================================
908 This routine is used to do packet parsing and classification for Tx packet
909 to STA device, and it will en-queue packets to our TxSwQueue depends on AC
913 pAd Pointer to our adapter
914 pPacket Pointer to send packet
917 NDIS_STATUS_SUCCESS If success to queue the packet into TxSwQueue.
918 NDIS_STATUS_FAILURE If failed to do en-queue.
921 You only can put OS-indepened & STA related code in here.
922 ========================================================================
924 int STASendPacket(struct rt_rtmp_adapter *pAd, void *pPacket)
926 struct rt_packet_info PacketInfo;
932 u8 QueIdx, UserPriority;
933 struct rt_mac_table_entry *pEntry = NULL;
934 unsigned int IrqFlags;
938 /* Prepare packet information structure for buffer descriptor */
939 /* chained within a single NDIS packet. */
940 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
942 if (pSrcBufVA == NULL) {
943 DBGPRINT(RT_DEBUG_ERROR,
944 ("STASendPacket --> pSrcBufVA == NULL !SrcBufLen=%x\n",
946 /* Resourece is low, system did not allocate virtual address */
947 /* return NDIS_STATUS_FAILURE directly to upper layer */
948 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
949 return NDIS_STATUS_FAILURE;
952 if (SrcBufLen < 14) {
953 DBGPRINT(RT_DEBUG_ERROR,
954 ("STASendPacket --> Ndis Packet buffer error!\n"));
955 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
956 return (NDIS_STATUS_FAILURE);
958 /* In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry. */
959 /* Note multicast packets in adhoc also use BSSID_WCID index. */
963 pEntry = &pAd->MacTab.Content[BSSID_WCID];
964 RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID);
965 Rate = pAd->CommonCfg.TxRate;
967 } else if (ADHOC_ON(pAd)) {
968 if (*pSrcBufVA & 0x01) {
969 RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID);
970 pEntry = &pAd->MacTab.Content[MCAST_WCID];
972 pEntry = MacTableLookup(pAd, pSrcBufVA);
974 Rate = pAd->CommonCfg.TxRate;
979 DBGPRINT(RT_DEBUG_ERROR,
980 ("STASendPacket->Cannot find pEntry(%pM) in MacTab!\n",
982 /* Resourece is low, system did not allocate virtual address */
983 /* return NDIS_STATUS_FAILURE directly to upper layer */
984 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
985 return NDIS_STATUS_FAILURE;
990 RTMP_SET_PACKET_WCID(pPacket, (u8)pEntry->Aid);
993 /* Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags. */
994 /* Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL). */
995 RTMPCheckEtherType(pAd, pPacket);
998 /* WPA 802.1x secured port control - drop all non-802.1x frame before port secured */
1000 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1001 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1002 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1003 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1004 || (pAd->StaCfg.IEEE8021X == TRUE)
1006 && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)
1007 || (pAd->StaCfg.MicErrCnt >= 2))
1008 && (RTMP_GET_PACKET_EAPOL(pPacket) == FALSE)
1010 DBGPRINT(RT_DEBUG_TRACE,
1011 ("STASendPacket --> Drop packet before port secured!\n"));
1012 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1014 return (NDIS_STATUS_FAILURE);
1017 /* STEP 1. Decide number of fragments required to deliver this MSDU. */
1018 /* The estimation here is not very accurate because difficult to */
1019 /* take encryption overhead into consideration here. The result */
1020 /* "NumberOfFrag" is then just used to pre-check if enough free */
1021 /* TXD are available to hold this MSDU. */
1023 if (*pSrcBufVA & 0x01) /* fragmentation not allowed on multicast & broadcast */
1025 else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))
1026 NumberOfFrag = 1; /* Aggregation overwhelms fragmentation */
1027 else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED))
1028 NumberOfFrag = 1; /* Aggregation overwhelms fragmentation */
1029 else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX)
1030 || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD))
1031 NumberOfFrag = 1; /* MIMO RATE overwhelms fragmentation */
1033 /* The calculated "NumberOfFrag" is a rough estimation because of various */
1034 /* encryption/encapsulation overhead not taken into consideration. This number is just */
1035 /* used to make sure enough free TXD are available before fragmentation takes place. */
1036 /* In case the actual required number of fragments of an NDIS packet */
1037 /* excceeds "NumberOfFrag"caculated here and not enough free TXD available, the */
1038 /* last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of */
1039 /* resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should */
1040 /* rarely happen and the penalty is just like a TX RETRY fail. Affordable. */
1043 (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 -
1046 ((PacketInfo.TotalPacketLength - LENGTH_802_3 +
1047 LENGTH_802_1_H) / AllowFragSize) + 1;
1048 /* To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size */
1049 if (((PacketInfo.TotalPacketLength - LENGTH_802_3 +
1050 LENGTH_802_1_H) % AllowFragSize) == 0) {
1055 /* Save fragment number to Ndis packet reserved field */
1056 RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
1058 /* STEP 2. Check the requirement of RTS: */
1059 /* If multiple fragment required, RTS is required only for the first fragment */
1060 /* if the fragment size large than RTS threshold */
1061 /* For RT28xx, Let ASIC send RTS/CTS */
1062 /* RTMP_SET_PACKET_RTS(pPacket, 0); */
1063 if (NumberOfFrag > 1)
1065 (pAd->CommonCfg.FragmentThreshold >
1066 pAd->CommonCfg.RtsThreshold) ? 1 : 0;
1069 (PacketInfo.TotalPacketLength >
1070 pAd->CommonCfg.RtsThreshold) ? 1 : 0;
1072 /* Save RTS requirement to Ndis packet reserved field */
1073 RTMP_SET_PACKET_RTS(pPacket, RTSRequired);
1074 RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate);
1077 /* STEP 3. Traffic classification. outcome = <UserPriority, QueIdx> */
1081 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
1082 CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE)) {
1084 u8 LlcSnapLen = 0, Byte0, Byte1;
1086 /* get Ethernet protocol field */
1088 (u16)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
1089 if (Protocol <= 1500) {
1090 /* get Ethernet protocol field from LLC/SNAP */
1091 if (Sniff2BytesFromNdisBuffer
1092 (PacketInfo.pFirstBuffer, LENGTH_802_3 + 6,
1093 &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1096 Protocol = (u16)((Byte0 << 8) + Byte1);
1099 /* always AC_BE for non-IP packet */
1100 if (Protocol != 0x0800)
1104 if (Sniff2BytesFromNdisBuffer
1105 (PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen,
1106 &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1109 /* return AC_BE if packet is not IPv4 */
1110 if ((Byte0 & 0xf0) != 0x40)
1114 UserPriority = (Byte1 & 0xe0) >> 5;
1115 QueIdx = MapUserPriorityToAccessCategory[UserPriority];
1117 /* TODO: have to check ACM bit. apply TSPEC if ACM is ON */
1118 /* TODO: downgrade UP & QueIdx before passing ACM */
1120 Under WMM ACM control, we dont need to check the bit;
1121 Or when a TSPEC is built for VO but we will change to issue
1122 BA session for BE here, so we will not use BA to send VO packets.
1124 if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx]) {
1131 RTMP_SET_PACKET_UP(pPacket, UserPriority);
1133 /* Make sure SendTxWait queue resource won't be used by other threads */
1134 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1135 if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE) {
1136 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1137 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1139 return NDIS_STATUS_FAILURE;
1141 InsertTailQueueAc(pAd, pEntry, &pAd->TxSwQueue[QueIdx],
1142 PACKET_TO_QUEUE_ENTRY(pPacket));
1144 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1146 if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE) &&
1147 IS_HT_STA(pEntry)) {
1148 /*struct rt_mac_table_entry *pMacEntry = &pAd->MacTab.Content[BSSID_WCID]; */
1149 if (((pEntry->TXBAbitmap & (1 << UserPriority)) == 0) &&
1150 ((pEntry->BADeclineBitmap & (1 << UserPriority)) == 0) &&
1151 (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
1152 /* For IOT compatibility, if */
1153 /* 1. It is Ralink chip or */
1154 /* 2. It is OPEN or AES mode, */
1155 /* then BA session can be bulit. */
1156 && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0)
1157 || (pEntry->WepStatus != Ndis802_11WEPEnabled
1158 && pEntry->WepStatus !=
1159 Ndis802_11Encryption2Enabled))
1161 BAOriSessionSetUp(pAd, pEntry, UserPriority, 0, 10,
1166 pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; /* TODO: for debug only. to be removed */
1167 return NDIS_STATUS_SUCCESS;
1171 ========================================================================
1173 Routine Description:
1174 This subroutine will scan through releative ring descriptor to find
1175 out avaliable free ring descriptor and compare with request size.
1178 pAd Pointer to our adapter
1179 QueIdx Selected TX Ring
1182 NDIS_STATUS_FAILURE Not enough free descriptor
1183 NDIS_STATUS_SUCCESS Enough free descriptor
1185 IRQL = PASSIVE_LEVEL
1186 IRQL = DISPATCH_LEVEL
1190 ========================================================================
1193 int RTMPFreeTXDRequest(struct rt_rtmp_adapter *pAd,
1195 u8 NumberRequired, u8 *FreeNumberIs)
1197 unsigned long FreeNumber = 0;
1198 int Status = NDIS_STATUS_FAILURE;
1205 if (pAd->TxRing[QueIdx].TxSwFreeIdx >
1206 pAd->TxRing[QueIdx].TxCpuIdx)
1208 pAd->TxRing[QueIdx].TxSwFreeIdx -
1209 pAd->TxRing[QueIdx].TxCpuIdx - 1;
1212 pAd->TxRing[QueIdx].TxSwFreeIdx + TX_RING_SIZE -
1213 pAd->TxRing[QueIdx].TxCpuIdx - 1;
1215 if (FreeNumber >= NumberRequired)
1216 Status = NDIS_STATUS_SUCCESS;
1220 if (pAd->MgmtRing.TxSwFreeIdx > pAd->MgmtRing.TxCpuIdx)
1222 pAd->MgmtRing.TxSwFreeIdx - pAd->MgmtRing.TxCpuIdx -
1226 pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE -
1227 pAd->MgmtRing.TxCpuIdx - 1;
1229 if (FreeNumber >= NumberRequired)
1230 Status = NDIS_STATUS_SUCCESS;
1234 DBGPRINT(RT_DEBUG_ERROR,
1235 ("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1238 *FreeNumberIs = (u8)FreeNumber;
1242 #endif /* RTMP_MAC_PCI // */
1245 Actually, this function used to check if the TxHardware Queue still has frame need to send.
1246 If no frame need to send, go to sleep, else, still wake up.
1248 int RTMPFreeTXDRequest(struct rt_rtmp_adapter *pAd,
1250 u8 NumberRequired, u8 *FreeNumberIs)
1252 /*unsigned long FreeNumber = 0; */
1253 int Status = NDIS_STATUS_FAILURE;
1254 unsigned long IrqFlags;
1255 struct rt_ht_tx_context *pHTTXContext;
1263 pHTTXContext = &pAd->TxContext[QueIdx];
1264 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx],
1266 if ((pHTTXContext->CurWritePosition !=
1267 pHTTXContext->ENextBulkOutPosition)
1268 || (pHTTXContext->IRPPending == TRUE)) {
1269 Status = NDIS_STATUS_FAILURE;
1271 Status = NDIS_STATUS_SUCCESS;
1273 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx],
1278 if (pAd->MgmtRing.TxSwFreeIdx != MGMT_RING_SIZE)
1279 Status = NDIS_STATUS_FAILURE;
1281 Status = NDIS_STATUS_SUCCESS;
1284 DBGPRINT(RT_DEBUG_ERROR,
1285 ("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1291 #endif /* RTMP_MAC_USB // */
1293 void RTMPSendDisassociationFrame(struct rt_rtmp_adapter *pAd)
1297 void RTMPSendNullFrame(struct rt_rtmp_adapter *pAd,
1298 u8 TxRate, IN BOOLEAN bQosNull)
1301 unsigned long Length;
1302 struct rt_header_802_11 * pHeader_802_11;
1304 /* WPA 802.1x secured port control */
1305 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1306 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1307 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1308 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1309 || (pAd->StaCfg.IEEE8021X == TRUE)
1310 ) && (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) {
1314 NdisZeroMemory(NullFrame, 48);
1315 Length = sizeof(struct rt_header_802_11);
1317 pHeader_802_11 = (struct rt_header_802_11 *) NullFrame;
1319 pHeader_802_11->FC.Type = BTYPE_DATA;
1320 pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
1321 pHeader_802_11->FC.ToDs = 1;
1322 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1323 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1324 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1326 if (pAd->CommonCfg.bAPSDForcePowerSave) {
1327 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1329 pHeader_802_11->FC.PwrMgmt =
1330 (pAd->StaCfg.Psm == PWR_SAVE) ? 1 : 0;
1332 pHeader_802_11->Duration =
1333 pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
1336 pHeader_802_11->Sequence = pAd->Sequence;
1338 /* Prepare QosNull function frame */
1340 pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
1342 /* copy QOS control bytes */
1343 NullFrame[Length] = 0;
1344 NullFrame[Length + 1] = 0;
1345 Length += 2; /* if pad with 2 bytes for alignment, APSD will fail */
1348 HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
1352 /* IRQL = DISPATCH_LEVEL */
1353 void RTMPSendRTSFrame(struct rt_rtmp_adapter *pAd,
1355 IN unsigned int NextMpduSize,
1358 u16 AckDuration, u8 QueIdx, u8 FrameGap)
1362 /* -------------------------------------------------------- */
1363 /* FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM */
1364 /* Find the WPA key, either Group or Pairwise Key */
1365 /* LEAP + TKIP also use WPA key. */
1366 /* -------------------------------------------------------- */
1367 /* Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst */
1368 /* In Cisco CCX 2.0 Leap Authentication */
1369 /* WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey */
1370 /* Instead of the SharedKey, SharedKey Length may be Zero. */
1371 void STAFindCipherAlgorithm(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
1373 NDIS_802_11_ENCRYPTION_STATUS Cipher; /* To indicate cipher used for this packet */
1374 u8 CipherAlg = CIPHER_NONE; /* cipher alogrithm */
1377 struct rt_cipher_key *pKey = NULL;
1379 pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
1383 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1384 Cipher = pAd->StaCfg.GroupCipher; /* Cipher for Multicast or Broadcast */
1386 Cipher = pAd->StaCfg.PairCipher; /* Cipher for Unicast */
1388 if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket)) {
1389 ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <=
1392 /* 4-way handshaking frame must be clear */
1393 if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame))
1394 && (pAd->SharedKey[BSS0][0].CipherAlg)
1395 && (pAd->SharedKey[BSS0][0].KeyLen)) {
1396 CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1399 } else if (Cipher == Ndis802_11Encryption1Enabled) {
1400 KeyIdx = pAd->StaCfg.DefaultKeyId;
1401 } else if ((Cipher == Ndis802_11Encryption2Enabled) ||
1402 (Cipher == Ndis802_11Encryption3Enabled)) {
1403 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) /* multicast */
1404 KeyIdx = pAd->StaCfg.DefaultKeyId;
1405 else if (pAd->SharedKey[BSS0][0].KeyLen)
1408 KeyIdx = pAd->StaCfg.DefaultKeyId;
1412 CipherAlg = CIPHER_NONE;
1413 else if ((Cipher == Ndis802_11EncryptionDisabled)
1414 || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
1415 CipherAlg = CIPHER_NONE;
1416 else if (pAd->StaCfg.WpaSupplicantUP &&
1417 (Cipher == Ndis802_11Encryption1Enabled) &&
1418 (pAd->StaCfg.IEEE8021X == TRUE) &&
1419 (pAd->StaCfg.PortSecured ==
1420 WPA_802_1X_PORT_NOT_SECURED))
1421 CipherAlg = CIPHER_NONE;
1423 /*Header_802_11.FC.Wep = 1; */
1424 CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
1425 pKey = &pAd->SharedKey[BSS0][KeyIdx];
1429 pTxBlk->CipherAlg = CipherAlg;
1430 pTxBlk->pKey = pKey;
1433 void STABuildCommon802_11Header(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
1435 struct rt_header_802_11 *pHeader_802_11;
1438 /* MAKE A COMMON 802.11 HEADER */
1441 /* normal wlan header size : 24 octets */
1442 pTxBlk->MpduHeaderLen = sizeof(struct rt_header_802_11);
1445 (struct rt_header_802_11 *) & pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1447 NdisZeroMemory(pHeader_802_11, sizeof(struct rt_header_802_11));
1449 pHeader_802_11->FC.FrDs = 0;
1450 pHeader_802_11->FC.Type = BTYPE_DATA;
1451 pHeader_802_11->FC.SubType =
1452 ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA :
1455 if (pTxBlk->pMacEntry) {
1456 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS)) {
1457 pHeader_802_11->Sequence =
1458 pTxBlk->pMacEntry->NonQosDataSeq;
1459 pTxBlk->pMacEntry->NonQosDataSeq =
1460 (pTxBlk->pMacEntry->NonQosDataSeq + 1) & MAXSEQ;
1463 pHeader_802_11->Sequence =
1464 pTxBlk->pMacEntry->TxSeq[pTxBlk->
1466 pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] =
1467 (pTxBlk->pMacEntry->
1468 TxSeq[pTxBlk->UserPriority] + 1) & MAXSEQ;
1472 pHeader_802_11->Sequence = pAd->Sequence;
1473 pAd->Sequence = (pAd->Sequence + 1) & MAXSEQ; /* next sequence */
1476 pHeader_802_11->Frag = 0;
1478 pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1481 if (INFRA_ON(pAd)) {
1483 COPY_MAC_ADDR(pHeader_802_11->Addr1,
1484 pAd->CommonCfg.Bssid);
1485 COPY_MAC_ADDR(pHeader_802_11->Addr2,
1486 pAd->CurrentAddress);
1487 COPY_MAC_ADDR(pHeader_802_11->Addr3,
1488 pTxBlk->pSrcBufHeader);
1489 pHeader_802_11->FC.ToDs = 1;
1491 } else if (ADHOC_ON(pAd)) {
1492 COPY_MAC_ADDR(pHeader_802_11->Addr1,
1493 pTxBlk->pSrcBufHeader);
1494 COPY_MAC_ADDR(pHeader_802_11->Addr2,
1495 pAd->CurrentAddress);
1496 COPY_MAC_ADDR(pHeader_802_11->Addr3,
1497 pAd->CommonCfg.Bssid);
1498 pHeader_802_11->FC.ToDs = 0;
1502 if (pTxBlk->CipherAlg != CIPHER_NONE)
1503 pHeader_802_11->FC.Wep = 1;
1505 /* ----------------------------------------------------------------- */
1506 /* STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later. */
1507 /* ----------------------------------------------------------------- */
1508 if (pAd->CommonCfg.bAPSDForcePowerSave)
1509 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1511 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1514 void STABuildCache802_11Header(struct rt_rtmp_adapter *pAd,
1515 struct rt_tx_blk *pTxBlk, u8 * pHeader)
1517 struct rt_mac_table_entry *pMacEntry;
1518 struct rt_header_802_11 * pHeader80211;
1520 pHeader80211 = (struct rt_header_802_11 *) pHeader;
1521 pMacEntry = pTxBlk->pMacEntry;
1524 /* Update the cached 802.11 HEADER */
1527 /* normal wlan header size : 24 octets */
1528 pTxBlk->MpduHeaderLen = sizeof(struct rt_header_802_11);
1531 pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1534 pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
1535 pMacEntry->TxSeq[pTxBlk->UserPriority] =
1536 (pMacEntry->TxSeq[pTxBlk->UserPriority] + 1) & MAXSEQ;
1539 /* Check if the frame can be sent through DLS direct link interface */
1540 /* If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability) */
1542 /* The addr3 of normal packet send from DS is Dest Mac address. */
1544 COPY_MAC_ADDR(pHeader80211->Addr3,
1545 pAd->CommonCfg.Bssid);
1547 COPY_MAC_ADDR(pHeader80211->Addr3,
1548 pTxBlk->pSrcBufHeader);
1551 /* ----------------------------------------------------------------- */
1552 /* STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later. */
1553 /* ----------------------------------------------------------------- */
1554 if (pAd->CommonCfg.bAPSDForcePowerSave)
1555 pHeader80211->FC.PwrMgmt = PWR_SAVE;
1557 pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1560 static inline u8 *STA_Build_ARalink_Frame_Header(struct rt_rtmp_adapter *pAd,
1561 struct rt_tx_blk *pTxBlk)
1564 struct rt_header_802_11 *pHeader_802_11;
1567 struct rt_queue_entry *pQEntry;
1569 STAFindCipherAlgorithm(pAd, pTxBlk);
1570 STABuildCommon802_11Header(pAd, pTxBlk);
1572 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1573 pHeader_802_11 = (struct rt_header_802_11 *) pHeaderBufPtr;
1575 /* steal "order" bit to mark "aggregation" */
1576 pHeader_802_11->FC.Order = 1;
1578 /* skip common header */
1579 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1581 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) {
1583 /* build QOS Control bytes */
1585 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1587 *(pHeaderBufPtr + 1) = 0;
1589 pTxBlk->MpduHeaderLen += 2;
1591 /* padding at front of LLC header. LLC header should at 4-bytes aligment. */
1592 pTxBlk->HdrPadLen = (unsigned long)pHeaderBufPtr;
1593 pHeaderBufPtr = (u8 *)ROUND_UP(pHeaderBufPtr, 4);
1594 pTxBlk->HdrPadLen = (unsigned long)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1596 /* For RA Aggregation, */
1597 /* put the 2nd MSDU length(extra 2-byte field) after struct rt_qos_control in little endian format */
1598 pQEntry = pTxBlk->TxPacketList.Head;
1599 pNextPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1600 nextBufLen = GET_OS_PKT_LEN(pNextPacket);
1601 if (RTMP_GET_PACKET_VLAN(pNextPacket))
1602 nextBufLen -= LENGTH_802_1Q;
1604 *pHeaderBufPtr = (u8)nextBufLen & 0xff;
1605 *(pHeaderBufPtr + 1) = (u8)(nextBufLen >> 8);
1608 pTxBlk->MpduHeaderLen += 2;
1610 return pHeaderBufPtr;
1614 static inline u8 *STA_Build_AMSDU_Frame_Header(struct rt_rtmp_adapter *pAd,
1615 struct rt_tx_blk *pTxBlk)
1617 u8 *pHeaderBufPtr; /*, pSaveBufPtr; */
1618 struct rt_header_802_11 *pHeader_802_11;
1620 STAFindCipherAlgorithm(pAd, pTxBlk);
1621 STABuildCommon802_11Header(pAd, pTxBlk);
1623 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1624 pHeader_802_11 = (struct rt_header_802_11 *) pHeaderBufPtr;
1626 /* skip common header */
1627 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1630 /* build QOS Control bytes */
1632 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1637 *pHeaderBufPtr |= 0x80;
1639 *(pHeaderBufPtr + 1) = 0;
1641 pTxBlk->MpduHeaderLen += 2;
1643 /*pSaveBufPtr = pHeaderBufPtr; */
1646 /* padding at front of LLC header */
1647 /* LLC header should locate at 4-octets aligment */
1649 /* @@@ MpduHeaderLen excluding padding @@@ */
1651 pTxBlk->HdrPadLen = (unsigned long)pHeaderBufPtr;
1652 pHeaderBufPtr = (u8 *)ROUND_UP(pHeaderBufPtr, 4);
1653 pTxBlk->HdrPadLen = (unsigned long)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1655 return pHeaderBufPtr;
1659 void STA_AMPDU_Frame_Tx(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
1661 struct rt_header_802_11 *pHeader_802_11;
1664 struct rt_mac_table_entry *pMacEntry;
1666 struct rt_queue_entry *pQEntry;
1670 while (pTxBlk->TxPacketList.Head) {
1671 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1672 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1673 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) {
1674 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket,
1675 NDIS_STATUS_FAILURE);
1680 (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1682 pMacEntry = pTxBlk->pMacEntry;
1683 if (pMacEntry->isCached) {
1684 /* NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]! */
1685 NdisMoveMemory((u8 *)& pTxBlk->
1686 HeaderBuf[TXINFO_SIZE],
1687 (u8 *)& pMacEntry->CachedBuf[0],
1688 TXWI_SIZE + sizeof(struct rt_header_802_11));
1691 HeaderBuf[TXINFO_SIZE + TXWI_SIZE]);
1692 STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
1694 STAFindCipherAlgorithm(pAd, pTxBlk);
1695 STABuildCommon802_11Header(pAd, pTxBlk);
1698 &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1701 pHeader_802_11 = (struct rt_header_802_11 *) pHeaderBufPtr;
1703 /* skip common header */
1704 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1707 /* build QOS Control bytes */
1709 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1710 *(pHeaderBufPtr + 1) = 0;
1712 pTxBlk->MpduHeaderLen += 2;
1716 /* HTC control filed following QoS field */
1718 if ((pAd->CommonCfg.bRdg == TRUE)
1719 && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry,
1720 fCLIENT_STATUS_RDG_CAPABLE)) {
1721 if (pMacEntry->isCached == FALSE) {
1723 pHeader_802_11->FC.Order = 1;
1725 NdisZeroMemory(pHeaderBufPtr, 4);
1726 *(pHeaderBufPtr + 3) |= 0x80;
1729 pTxBlk->MpduHeaderLen += 4;
1731 /*pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE; */
1732 ASSERT(pTxBlk->MpduHeaderLen >= 24);
1734 /* skip 802.3 header */
1735 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1736 pTxBlk->SrcBufLen -= LENGTH_802_3;
1740 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1741 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1744 /* padding at front of LLC header */
1745 /* LLC header should locate at 4-octets aligment */
1747 /* @@@ MpduHeaderLen excluding padding @@@ */
1749 pTxBlk->HdrPadLen = (unsigned long)pHeaderBufPtr;
1750 pHeaderBufPtr = (u8 *)ROUND_UP(pHeaderBufPtr, 4);
1751 pTxBlk->HdrPadLen = (unsigned long)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1756 /* Insert LLC-SNAP encapsulation - 8 octets */
1758 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->
1761 pExtraLlcSnapEncap);
1762 if (pTxBlk->pExtraLlcSnapEncap) {
1763 NdisMoveMemory(pHeaderBufPtr,
1764 pTxBlk->pExtraLlcSnapEncap, 6);
1766 /* get 2 octets (TypeofLen) */
1767 NdisMoveMemory(pHeaderBufPtr,
1768 pTxBlk->pSrcBufData - 2, 2);
1770 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1775 if (pMacEntry->isCached) {
1776 RTMPWriteTxWI_Cache(pAd,
1777 (struct rt_txwi *) (&pTxBlk->
1782 RTMPWriteTxWI_Data(pAd,
1783 (struct rt_txwi *) (&pTxBlk->
1788 NdisZeroMemory((u8 *)(&pMacEntry->CachedBuf[0]),
1789 sizeof(pMacEntry->CachedBuf));
1790 NdisMoveMemory((u8 *)(&pMacEntry->CachedBuf[0]),
1792 HeaderBuf[TXINFO_SIZE]),
1795 HeaderBuf[TXINFO_SIZE])));
1796 pMacEntry->isCached = TRUE;
1799 /* calculate Transmitted AMPDU count and ByteCount */
1801 pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.
1803 pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.
1804 QuadPart += pTxBlk->SrcBufLen;
1807 /*FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); */
1809 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1814 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
1815 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1817 pAd->RalinkCounters.KickTxCount++;
1818 pAd->RalinkCounters.OneSecTxDoneCount++;
1823 void STA_AMSDU_Frame_Tx(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
1827 u16 subFramePayloadLen = 0; /* AMSDU Subframe length without AMSDU-Header / Padding. */
1828 u16 totalMPDUSize = 0;
1831 u16 FirstTx = 0, LastTxIdx = 0;
1834 struct rt_queue_entry *pQEntry;
1838 ASSERT((pTxBlk->TxPacketList.Number > 1));
1840 while (pTxBlk->TxPacketList.Head) {
1841 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1842 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1843 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) {
1844 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket,
1845 NDIS_STATUS_FAILURE);
1850 (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1852 /* skip 802.3 header */
1853 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1854 pTxBlk->SrcBufLen -= LENGTH_802_3;
1858 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1859 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1862 if (frameNum == 0) {
1864 STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
1866 /* NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled. */
1867 RTMPWriteTxWI_Data(pAd,
1868 (struct rt_txwi *) (&pTxBlk->
1873 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
1875 ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD +
1877 4) - (LENGTH_AMSDU_SUBFRAMEHEAD +
1878 subFramePayloadLen);
1879 NdisZeroMemory(pHeaderBufPtr,
1880 padding + LENGTH_AMSDU_SUBFRAMEHEAD);
1881 pHeaderBufPtr += padding;
1882 pTxBlk->MpduHeaderLen = padding;
1886 /* A-MSDU subframe */
1887 /* DA(6)+SA(6)+Length(2) + LLC/SNAP Encap */
1889 subFrameHeader = pHeaderBufPtr;
1890 subFramePayloadLen = pTxBlk->SrcBufLen;
1892 NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
1894 pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
1895 pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
1898 /* Insert LLC-SNAP encapsulation - 8 octets */
1900 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData - 2,
1901 pTxBlk->pExtraLlcSnapEncap);
1903 subFramePayloadLen = pTxBlk->SrcBufLen;
1905 if (pTxBlk->pExtraLlcSnapEncap) {
1906 NdisMoveMemory(pHeaderBufPtr,
1907 pTxBlk->pExtraLlcSnapEncap, 6);
1909 /* get 2 octets (TypeofLen) */
1910 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData - 2,
1913 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1914 subFramePayloadLen += LENGTH_802_1_H;
1916 /* update subFrame Length field */
1917 subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
1918 subFrameHeader[13] = subFramePayloadLen & 0xFF;
1920 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1924 HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum,
1928 HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum,
1933 pAd->RalinkCounters.KickTxCount++;
1934 pAd->RalinkCounters.OneSecTxDoneCount++;
1936 /* calculate Transmitted AMSDU Count and ByteCount */
1938 pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart++;
1939 pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart +=
1945 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
1946 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
1951 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
1952 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1955 void STA_Legacy_Frame_Tx(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
1957 struct rt_header_802_11 *pHeader_802_11;
1961 struct rt_queue_entry *pQEntry;
1965 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1966 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1967 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) {
1968 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1972 if (pTxBlk->TxFrameType == TX_MCAST_FRAME) {
1973 INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
1976 if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
1977 TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
1979 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
1981 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1983 if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
1984 pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
1986 STAFindCipherAlgorithm(pAd, pTxBlk);
1987 STABuildCommon802_11Header(pAd, pTxBlk);
1989 /* skip 802.3 header */
1990 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1991 pTxBlk->SrcBufLen -= LENGTH_802_3;
1995 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1996 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1999 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2000 pHeader_802_11 = (struct rt_header_802_11 *) pHeaderBufPtr;
2002 /* skip common header */
2003 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2005 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) {
2007 /* build QOS Control bytes */
2010 ((pTxBlk->UserPriority & 0x0F) | (pAd->CommonCfg.
2013 *(pHeaderBufPtr + 1) = 0;
2015 pTxBlk->MpduHeaderLen += 2;
2017 /* The remaining content of MPDU header should locate at 4-octets aligment */
2018 pTxBlk->HdrPadLen = (unsigned long)pHeaderBufPtr;
2019 pHeaderBufPtr = (u8 *)ROUND_UP(pHeaderBufPtr, 4);
2020 pTxBlk->HdrPadLen = (unsigned long)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2025 /* Insert LLC-SNAP encapsulation - 8 octets */
2028 /* if original Ethernet frame contains no LLC/SNAP, */
2029 /* then an extra LLC/SNAP encap is required */
2031 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader,
2032 pTxBlk->pExtraLlcSnapEncap);
2033 if (pTxBlk->pExtraLlcSnapEncap) {
2036 NdisMoveMemory(pHeaderBufPtr,
2037 pTxBlk->pExtraLlcSnapEncap, 6);
2040 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2041 /* get 2 octets (TypeofLen) */
2042 NdisMoveMemory(pHeaderBufPtr,
2043 pTxBlk->pSrcBufHeader + 12 + vlan_size,
2046 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2052 /* prepare for TXWI */
2053 /* use Wcid as Key Index */
2056 RTMPWriteTxWI_Data(pAd, (struct rt_txwi *) (&pTxBlk->HeaderBuf[TXINFO_SIZE]),
2059 /*FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); */
2061 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
2063 pAd->RalinkCounters.KickTxCount++;
2064 pAd->RalinkCounters.OneSecTxDoneCount++;
2069 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2070 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2073 void STA_ARalink_Frame_Tx(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
2077 u16 totalMPDUSize = 0;
2078 u16 FirstTx, LastTxIdx;
2081 struct rt_queue_entry *pQEntry;
2085 ASSERT((pTxBlk->TxPacketList.Number == 2));
2087 FirstTx = LastTxIdx = 0; /* Is it ok init they as 0? */
2088 while (pTxBlk->TxPacketList.Head) {
2089 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2090 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2092 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) {
2093 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket,
2094 NDIS_STATUS_FAILURE);
2099 (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2101 /* skip 802.3 header */
2102 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2103 pTxBlk->SrcBufLen -= LENGTH_802_3;
2107 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2108 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2111 if (frameNum == 0) { /* For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header */
2114 STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
2116 /* It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount */
2117 /* will be updated after final frame was handled. */
2118 RTMPWriteTxWI_Data(pAd,
2119 (struct rt_txwi *) (&pTxBlk->
2125 /* Insert LLC-SNAP encapsulation - 8 octets */
2127 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->
2130 pExtraLlcSnapEncap);
2132 if (pTxBlk->pExtraLlcSnapEncap) {
2133 NdisMoveMemory(pHeaderBufPtr,
2134 pTxBlk->pExtraLlcSnapEncap, 6);
2136 /* get 2 octets (TypeofLen) */
2137 NdisMoveMemory(pHeaderBufPtr,
2138 pTxBlk->pSrcBufData - 2, 2);
2140 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2142 } else { /* For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0. */
2144 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
2145 pTxBlk->MpduHeaderLen = 0;
2147 /* A-Ralink sub-sequent frame header is the same as 802.3 header. */
2148 /* DA(6)+SA(6)+FrameType(2) */
2149 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader,
2151 pHeaderBufPtr += 12;
2152 /* get 2 octets (TypeofLen) */
2153 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData - 2,
2156 pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD;
2159 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2161 /*FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); */
2164 HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum,
2168 HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum,
2173 pAd->RalinkCounters.OneSecTxAggregationCount++;
2174 pAd->RalinkCounters.KickTxCount++;
2175 pAd->RalinkCounters.OneSecTxDoneCount++;
2179 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2180 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2185 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2186 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2190 void STA_Fragment_Frame_Tx(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
2192 struct rt_header_802_11 *pHeader_802_11;
2196 struct rt_packet_info PacketInfo;
2197 u16 EncryptionOverhead = 0;
2198 u32 FreeMpduSize, SrcRemainingBytes;
2202 struct rt_queue_entry *pQEntry;
2203 HTTRANSMIT_SETTING *pTransmit;
2207 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2208 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2209 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) {
2210 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2214 ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag));
2215 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2217 STAFindCipherAlgorithm(pAd, pTxBlk);
2218 STABuildCommon802_11Header(pAd, pTxBlk);
2220 if (pTxBlk->CipherAlg == CIPHER_TKIP) {
2222 duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket);
2223 if (pTxBlk->pPacket == NULL)
2225 RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo,
2226 &pTxBlk->pSrcBufHeader,
2227 &pTxBlk->SrcBufLen);
2229 /* skip 802.3 header */
2230 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2231 pTxBlk->SrcBufLen -= LENGTH_802_3;
2235 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2236 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2239 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2240 pHeader_802_11 = (struct rt_header_802_11 *) pHeaderBufPtr;
2242 /* skip common header */
2243 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2245 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) {
2247 /* build QOS Control bytes */
2249 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2251 *(pHeaderBufPtr + 1) = 0;
2253 pTxBlk->MpduHeaderLen += 2;
2256 /* padding at front of LLC header */
2257 /* LLC header should locate at 4-octets aligment */
2259 pTxBlk->HdrPadLen = (unsigned long)pHeaderBufPtr;
2260 pHeaderBufPtr = (u8 *)ROUND_UP(pHeaderBufPtr, 4);
2261 pTxBlk->HdrPadLen = (unsigned long)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2264 /* Insert LLC-SNAP encapsulation - 8 octets */
2267 /* if original Ethernet frame contains no LLC/SNAP, */
2268 /* then an extra LLC/SNAP encap is required */
2270 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader,
2271 pTxBlk->pExtraLlcSnapEncap);
2272 if (pTxBlk->pExtraLlcSnapEncap) {
2275 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2278 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2279 /* get 2 octets (TypeofLen) */
2280 NdisMoveMemory(pHeaderBufPtr,
2281 pTxBlk->pSrcBufHeader + 12 + vlan_size, 2);
2283 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2286 /* If TKIP is used and fragmentation is required. Driver has to */
2287 /* append TKIP MIC at tail of the scatter buffer */
2288 /* MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC */
2289 if (pTxBlk->CipherAlg == CIPHER_TKIP) {
2290 RTMPCalculateMICValue(pAd, pTxBlk->pPacket,
2291 pTxBlk->pExtraLlcSnapEncap, pTxBlk->pKey,
2294 /* NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust */
2295 /* to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress. */
2296 NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen,
2297 &pAd->PrivateInfo.Tx.MIC[0], 8);
2298 /*skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8); */
2299 pTxBlk->SrcBufLen += 8;
2300 pTxBlk->TotalFrameLen += 8;
2301 pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC;
2304 /* calcuate the overhead bytes that encryption algorithm may add. This */
2305 /* affects the calculate of "duration" field */
2307 if ((pTxBlk->CipherAlg == CIPHER_WEP64)
2308 || (pTxBlk->CipherAlg == CIPHER_WEP128))
2309 EncryptionOverhead = 8; /*WEP: IV[4] + ICV[4]; */
2310 else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC)
2311 EncryptionOverhead = 12; /*TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength */
2312 else if (pTxBlk->CipherAlg == CIPHER_TKIP)
2313 EncryptionOverhead = 20; /*TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8] */
2314 else if (pTxBlk->CipherAlg == CIPHER_AES)
2315 EncryptionOverhead = 16; /* AES: IV[4] + EIV[4] + MIC[8] */
2317 EncryptionOverhead = 0;
2319 pTransmit = pTxBlk->pTransmit;
2320 /* Decide the TX rate */
2321 if (pTransmit->field.MODE == MODE_CCK)
2322 pTxBlk->TxRate = pTransmit->field.MCS;
2323 else if (pTransmit->field.MODE == MODE_OFDM)
2324 pTxBlk->TxRate = pTransmit->field.MCS + RATE_FIRST_OFDM_RATE;
2326 pTxBlk->TxRate = RATE_6_5;
2328 /* decide how much time an ACK/CTS frame will consume in the air */
2329 if (pTxBlk->TxRate <= RATE_LAST_OFDM_RATE)
2331 RTMPCalcDuration(pAd,
2332 pAd->CommonCfg.ExpectedACKRate[pTxBlk->
2336 AckDuration = RTMPCalcDuration(pAd, RATE_6_5, 14);
2338 /* Init the total payload length of this frame. */
2339 SrcRemainingBytes = pTxBlk->SrcBufLen;
2341 pTxBlk->TotalFragNum = 0xff;
2345 FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC;
2347 FreeMpduSize -= pTxBlk->MpduHeaderLen;
2349 if (SrcRemainingBytes <= FreeMpduSize) { /* this is the last or only fragment */
2351 pTxBlk->SrcBufLen = SrcRemainingBytes;
2353 pHeader_802_11->FC.MoreFrag = 0;
2354 pHeader_802_11->Duration =
2355 pAd->CommonCfg.Dsifs + AckDuration;
2357 /* Indicate the lower layer that this's the last fragment. */
2358 pTxBlk->TotalFragNum = fragNum;
2359 } else { /* more fragment is required */
2361 pTxBlk->SrcBufLen = FreeMpduSize;
2364 min(((u32)SrcRemainingBytes - pTxBlk->SrcBufLen),
2365 ((u32)pAd->CommonCfg.FragmentThreshold));
2366 pHeader_802_11->FC.MoreFrag = 1;
2367 pHeader_802_11->Duration =
2368 (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) +
2369 RTMPCalcDuration(pAd, pTxBlk->TxRate,
2370 NextMpduSize + EncryptionOverhead);
2374 pTxBlk->FrameGap = IFS_HTTXOP;
2376 pTxBlk->FrameGap = IFS_SIFS;
2378 RTMPWriteTxWI_Data(pAd,
2379 (struct rt_txwi *) (&pTxBlk->
2380 HeaderBuf[TXINFO_SIZE]),
2383 HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber);
2385 pAd->RalinkCounters.KickTxCount++;
2386 pAd->RalinkCounters.OneSecTxDoneCount++;
2388 /* Update the frame number, remaining size of the NDIS packet payload. */
2390 /* space for 802.11 header. */
2391 if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap)
2392 pTxBlk->MpduHeaderLen -= LENGTH_802_1_H;
2395 SrcRemainingBytes -= pTxBlk->SrcBufLen;
2396 pTxBlk->pSrcBufData += pTxBlk->SrcBufLen;
2398 pHeader_802_11->Frag++; /* increase Frag # */
2400 } while (SrcRemainingBytes > 0);
2405 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2406 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2409 #define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \
2410 while(_pTxBlk->TxPacketList.Head) \
2412 _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList); \
2413 RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \
2417 ========================================================================
2419 Routine Description:
2420 Copy frame from waiting queue into relative ring buffer and set
2421 appropriate ASIC register to kick hardware encryption before really
2425 pAd Pointer to our adapter
2426 void * Pointer to outgoing Ndis frame
2427 NumberOfFrag Number of fragment required
2432 IRQL = DISPATCH_LEVEL
2436 ========================================================================
2438 int STAHardTransmit(struct rt_rtmp_adapter *pAd,
2439 struct rt_tx_blk *pTxBlk, u8 QueIdx)
2442 struct rt_queue_entry *pQEntry;
2444 /* --------------------------------------------- */
2445 /* STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION. */
2446 /* --------------------------------------------- */
2448 ASSERT(pTxBlk->TxPacketList.Number);
2449 if (pTxBlk->TxPacketList.Head == NULL) {
2450 DBGPRINT(RT_DEBUG_ERROR,
2451 ("pTxBlk->TotalFrameNum == %ld!\n",
2452 pTxBlk->TxPacketList.Number));
2453 return NDIS_STATUS_FAILURE;
2456 pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head);
2458 /* ------------------------------------------------------------------ */
2459 /* STEP 1. WAKE UP PHY */
2460 /* outgoing frame always wakeup PHY to prevent frame lost and */
2461 /* turn off PSM bit to improve performance */
2462 /* ------------------------------------------------------------------ */
2463 /* not to change PSM bit, just send this frame out? */
2464 if ((pAd->StaCfg.Psm == PWR_SAVE)
2465 && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) {
2466 DBGPRINT_RAW(RT_DEBUG_INFO, ("AsicForceWakeup At HardTx\n"));
2468 AsicForceWakeup(pAd, TRUE);
2469 #endif /* RTMP_MAC_PCI // */
2471 RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_FORCE_WAKE_UP, NULL, 0);
2472 #endif /* RTMP_MAC_USB // */
2474 /* It should not change PSM bit, when APSD turn on. */
2476 (pAd->CommonCfg.bAPSDCapable
2477 && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
2478 && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE))
2479 || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
2480 || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket))) {
2481 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
2482 (pAd->StaCfg.WindowsPowerMode ==
2483 Ndis802_11PowerModeFast_PSP))
2484 RTMP_SET_PSM_BIT(pAd, PWR_ACTIVE);
2487 switch (pTxBlk->TxFrameType) {
2488 case TX_AMPDU_FRAME:
2489 STA_AMPDU_Frame_Tx(pAd, pTxBlk);
2491 case TX_AMSDU_FRAME:
2492 STA_AMSDU_Frame_Tx(pAd, pTxBlk);
2494 case TX_LEGACY_FRAME:
2495 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2497 case TX_MCAST_FRAME:
2498 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2500 case TX_RALINK_FRAME:
2501 STA_ARalink_Frame_Tx(pAd, pTxBlk);
2504 STA_Fragment_Frame_Tx(pAd, pTxBlk);
2508 /* It should not happened! */
2509 DBGPRINT(RT_DEBUG_ERROR,
2510 ("Send a packet was not classified! It should not happen!\n"));
2511 while (pTxBlk->TxPacketList.Number) {
2513 RemoveHeadQueue(&pTxBlk->TxPacketList);
2514 pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2516 RELEASE_NDIS_PACKET(pAd, pPacket,
2517 NDIS_STATUS_FAILURE);
2523 return (NDIS_STATUS_SUCCESS);
2527 unsigned long HashBytesPolynomial(u8 * value, unsigned int len)
2529 unsigned char *word = value;
2530 unsigned int ret = 0;
2533 for (i = 0; i < len; i++) {
2535 ret ^= (unsigned int)(word[i]) << mod;
2536 ret ^= (unsigned int)(word[i]) >> (32 - mod);
2541 void Sta_Announce_or_Forward_802_3_Packet(struct rt_rtmp_adapter *pAd,
2546 announce_802_3_packet(pAd, pPacket);
2548 /* release packet */
2549 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);