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"
39 void STARxEAPOLFrameIndicate(struct rt_rtmp_adapter *pAd,
40 struct rt_mac_table_entry *pEntry,
41 struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
43 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
44 struct rt_rxwi * pRxWI = pRxBlk->pRxWI;
47 if (pAd->StaCfg.WpaSupplicantUP) {
48 /* All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon) */
49 /* TBD : process fragmented EAPol frames */
51 /* In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable */
52 if (pAd->StaCfg.IEEE8021X == TRUE &&
54 WpaCheckEapCode(pAd, pRxBlk->pData,
61 DBGPRINT_RAW(RT_DEBUG_TRACE,
62 ("Receive EAP-SUCCESS Packet\n"));
63 /*pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; */
64 STA_PORT_SECURED(pAd);
66 if (pAd->StaCfg.IEEE8021x_required_keys ==
68 idx = pAd->StaCfg.DesireSharedKeyId;
70 pAd->StaCfg.DesireSharedKey[idx].
73 pAd->StaCfg.DesireSharedKey[idx].
76 if (pAd->StaCfg.DesireSharedKey[idx].
79 struct rt_mac_table_entry *pEntry =
83 /* Set key material and cipherAlg to Asic */
84 AsicAddSharedKeyEntry(pAd, BSS0,
90 /* Assign group key info */
91 RTMPAddWcidAttributeEntry(pAd,
97 /* Assign pairwise key info */
98 RTMPAddWcidAttributeEntry(pAd,
104 pAd->IndicateMediaState =
105 NdisMediaStateConnected;
108 #endif /* RTMP_MAC_PCI // */
112 (struct rt_ndis_802_11_wep)
116 struct rt_ndis_802_11_wep keyinfo;
121 NdisZeroMemory(&WepKey,
125 DesireSharedKey[idx].KeyLen;
127 NdisMoveMemory(WepKey.keyinfo.
136 WepKey.keyinfo.KeyIndex =
138 WepKey.keyinfo.KeyLength = len;
139 pAd->SharedKey[BSS0][idx].
141 (u8)(len <= 5 ? 5 : 13);
143 pAd->IndicateMediaState =
144 NdisMediaStateConnected;
147 /* need to enqueue cmd to thread */
148 RTUSBEnqueueCmdFromNdis(pAd,
157 #endif /* RTMP_MAC_USB // */
158 /* For Preventing ShardKey Table is cleared by remove key procedure. */
159 pAd->SharedKey[BSS0][idx].
160 CipherAlg = CipherAlg;
161 pAd->SharedKey[BSS0][idx].
164 DesireSharedKey[idx].KeyLen;
178 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
182 /* Special DATA frame that has to pass to MLME */
183 /* 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process */
184 /* 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process */
186 pTmpBuf = pRxBlk->pData - LENGTH_802_11;
187 NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11);
188 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID,
191 LENGTH_802_11, pRxWI->RSSI0,
192 pRxWI->RSSI1, pRxWI->RSSI2,
194 DBGPRINT_RAW(RT_DEBUG_TRACE,
195 ("report EAPOL/AIRONET DATA to MLME (len=%d) !\n",
200 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
205 void STARxDataFrameAnnounce(struct rt_rtmp_adapter *pAd,
206 struct rt_mac_table_entry *pEntry,
207 struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
211 if (!RTMPCheckWPAframe
212 (pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID)) {
215 /* drop all non-EAP DATA frame before */
216 /* this client's Port-Access-Control is secured */
217 if (pRxBlk->pHeader->FC.Wep) {
218 /* unsupported cipher suite */
219 if (pAd->StaCfg.WepStatus ==
220 Ndis802_11EncryptionDisabled) {
222 RELEASE_NDIS_PACKET(pAd,
224 NDIS_STATUS_FAILURE);
228 /* encryption in-use but receive a non-EAPOL clear text frame, drop it */
229 if ((pAd->StaCfg.WepStatus !=
230 Ndis802_11EncryptionDisabled)
231 && (pAd->StaCfg.PortSecured ==
232 WPA_802_1X_PORT_NOT_SECURED)) {
234 RELEASE_NDIS_PACKET(pAd,
236 NDIS_STATUS_FAILURE);
241 RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP);
242 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK)) {
243 /* Normal legacy, AMPDU or AMSDU */
244 CmmRxnonRalinkFrameIndicate(pAd, pRxBlk,
249 CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk,
253 RX_BLK_SET_FLAG(pRxBlk, fRX_EAP);
255 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU)
256 && (pAd->CommonCfg.bDisableReordering == 0)) {
257 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
259 /* Determin the destination of the EAP frame */
260 /* to WPA state machine or upper layer */
261 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk,
267 /* For TKIP frame, calculate the MIC value */
268 BOOLEAN STACheckTkipMICValue(struct rt_rtmp_adapter *pAd,
269 struct rt_mac_table_entry *pEntry, struct rt_rx_blk *pRxBlk)
271 struct rt_header_802_11 * pHeader = pRxBlk->pHeader;
272 u8 *pData = pRxBlk->pData;
273 u16 DataSize = pRxBlk->DataSize;
274 u8 UserPriority = pRxBlk->UserPriority;
275 struct rt_cipher_key *pWpaKey;
278 pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex];
280 pDA = pHeader->Addr1;
281 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA)) {
282 pSA = pHeader->Addr3;
284 pSA = pHeader->Addr2;
287 if (RTMPTkipCompareMICValue(pAd,
292 UserPriority, DataSize) == FALSE) {
293 DBGPRINT_RAW(RT_DEBUG_ERROR, ("Rx MIC Value error 2\n"));
295 if (pAd->StaCfg.WpaSupplicantUP) {
296 WpaSendMicFailureToWpaSupplicant(pAd,
298 PAIRWISEKEY) ? TRUE :
301 RTMPReportMicError(pAd, pWpaKey);
305 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
306 NDIS_STATUS_FAILURE);
314 /* All Rx routines use struct rt_rx_blk structure to hande rx events */
315 /* It is very important to build pRxBlk attributes */
316 /* 1. pHeader pointer to 802.11 Header */
317 /* 2. pData pointer to payload including LLC (just skip Header) */
318 /* 3. set payload size including LLC to DataSize */
319 /* 4. set some flags with RX_BLK_SET_FLAG() */
321 void STAHandleRxDataFrame(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk)
323 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
324 struct rt_rxwi * pRxWI = pRxBlk->pRxWI;
325 struct rt_header_802_11 * pHeader = pRxBlk->pHeader;
326 void *pRxPacket = pRxBlk->pRxPacket;
327 BOOLEAN bFragment = FALSE;
328 struct rt_mac_table_entry *pEntry = NULL;
329 u8 FromWhichBSSID = BSS0;
333 /* before LINK UP, all DATA frames are rejected */
334 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) {
336 RELEASE_NDIS_PACKET(pAd, pRxPacket,
337 NDIS_STATUS_FAILURE);
340 /* Drop not my BSS frames */
341 if (pRxD->MyBss == 0) {
344 RELEASE_NDIS_PACKET(pAd, pRxPacket,
345 NDIS_STATUS_FAILURE);
350 pAd->RalinkCounters.RxCountSinceLastNULL++;
351 if (pAd->CommonCfg.bAPSDCapable
352 && pAd->CommonCfg.APEdcaParm.bAPSDCapable
353 && (pHeader->FC.SubType & 0x08)) {
355 DBGPRINT(RT_DEBUG_INFO, ("bAPSDCapable\n"));
358 pData = (u8 *)pHeader + LENGTH_802_11;
359 if ((*pData >> 4) & 0x01) {
360 DBGPRINT(RT_DEBUG_INFO,
361 ("RxDone- Rcv EOSP frame, driver may fall into sleep\n"));
362 pAd->CommonCfg.bInServicePeriod = FALSE;
364 /* Force driver to fall into sleep mode when rcv EOSP frame */
365 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) {
366 u16 TbttNumToNextWakeUp;
368 pAd->StaCfg.DtimPeriod;
371 NdisGetSystemUpTime(&Now);
376 pAd->CommonCfg.BeaconPeriod;
378 TbttNumToNextWakeUp =
379 pAd->StaCfg.DefaultListenCount;
380 if (OPSTATUS_TEST_FLAG
381 (pAd, fOP_STATUS_RECEIVE_DTIM)
382 && (TbttNumToNextWakeUp > NextDtim))
383 TbttNumToNextWakeUp = NextDtim;
385 RTMP_SET_PSM_BIT(pAd, PWR_SAVE);
386 /* if WMM-APSD is failed, try to disable following line */
387 AsicSleepThenAutoWakeup(pAd,
388 TbttNumToNextWakeUp);
392 if ((pHeader->FC.MoreData)
393 && (pAd->CommonCfg.bInServicePeriod)) {
394 DBGPRINT(RT_DEBUG_TRACE,
395 ("Sending another trigger frame when More Data bit is set to 1\n"));
398 /* Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame */
399 if ((pHeader->FC.SubType & 0x04)) /* bit 2 : no DATA */
402 RELEASE_NDIS_PACKET(pAd, pRxPacket,
403 NDIS_STATUS_FAILURE);
406 /* Drop not my BSS frame (we can not only check the MyBss bit in RxD) */
409 /* Infrastructure mode, check address 2 for BSSID */
411 (&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6)) {
412 /* Receive frame not my BSSID */
414 RELEASE_NDIS_PACKET(pAd, pRxPacket,
415 NDIS_STATUS_FAILURE);
418 } else /* Ad-Hoc mode or Not associated */
420 /* Ad-Hoc mode, check address 3 for BSSID */
422 (&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6)) {
423 /* Receive frame not my BSSID */
425 RELEASE_NDIS_PACKET(pAd, pRxPacket,
426 NDIS_STATUS_FAILURE);
434 if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE) {
435 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
437 /* 1. release packet if infra mode */
438 /* 2. new a pEntry if ad-hoc mode */
439 RELEASE_NDIS_PACKET(pAd, pRxPacket,
440 NDIS_STATUS_FAILURE);
444 /* infra or ad-hoc */
446 RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA);
447 ASSERT(pRxWI->WirelessCliID == BSSID_WCID);
449 /* check Atheros Client */
450 if ((pEntry->bIAmBadAtheros == FALSE) && (pRxD->AMPDU == 1)
451 && (pHeader->FC.Retry)) {
452 pEntry->bIAmBadAtheros = TRUE;
453 pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE;
454 pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE;
455 if (!STA_AES_ON(pAd)) {
456 AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE,
462 pRxBlk->pData = (u8 *) pHeader;
465 /* update RxBlk->pData, DataSize */
466 /* 802.11 Header, QOS, HTC, Hw Padding */
469 /* 1. skip 802.11 HEADER */
471 pRxBlk->pData += LENGTH_802_11;
472 pRxBlk->DataSize -= LENGTH_802_11;
476 if (pHeader->FC.SubType & 0x08) {
477 RX_BLK_SET_FLAG(pRxBlk, fRX_QOS);
478 UserPriority = *(pRxBlk->pData) & 0x0f;
479 /* bit 7 in QoS Control field signals the HT A-MSDU format */
480 if ((*pRxBlk->pData) & 0x80) {
481 RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU);
483 /* skip QOS contorl field */
485 pRxBlk->DataSize -= 2;
487 pRxBlk->UserPriority = UserPriority;
489 /* check if need to resend PS Poll when received packet with MoreData = 1 */
490 if ((pAd->StaCfg.Psm == PWR_SAVE) && (pHeader->FC.MoreData == 1)) {
491 if ((((UserPriority == 0) || (UserPriority == 3)) &&
492 pAd->CommonCfg.bAPSDAC_BE == 0) ||
493 (((UserPriority == 1) || (UserPriority == 2)) &&
494 pAd->CommonCfg.bAPSDAC_BK == 0) ||
495 (((UserPriority == 4) || (UserPriority == 5)) &&
496 pAd->CommonCfg.bAPSDAC_VI == 0) ||
497 (((UserPriority == 6) || (UserPriority == 7)) &&
498 pAd->CommonCfg.bAPSDAC_VO == 0)) {
499 /* non-UAPSD delivery-enabled AC */
500 RTMP_PS_POLL_ENQUEUE(pAd);
503 /* 3. Order bit: A-Ralink or HTC+ */
504 if (pHeader->FC.Order) {
505 #ifdef AGGREGATION_SUPPORT
506 if ((pRxWI->PHYMODE <= MODE_OFDM)
507 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)))
509 RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK);
511 #endif /* AGGREGATION_SUPPORT // */
513 RX_BLK_SET_FLAG(pRxBlk, fRX_HTC);
514 /* skip HTC contorl field */
516 pRxBlk->DataSize -= 4;
519 /* 4. skip HW padding */
521 /* just move pData pointer */
522 /* because DataSize excluding HW padding */
523 RX_BLK_SET_FLAG(pRxBlk, fRX_PAD);
528 RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU);
531 /* Case I Process Broadcast & Multicast data frame */
533 if (pRxD->Bcast || pRxD->Mcast) {
534 INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount);
536 /* Drop Mcast/Bcast frame with fragment bit on */
537 if (pHeader->FC.MoreFrag) {
539 RELEASE_NDIS_PACKET(pAd, pRxPacket,
540 NDIS_STATUS_FAILURE);
543 /* Filter out Bcast frame which AP relayed for us */
545 && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress)) {
547 RELEASE_NDIS_PACKET(pAd, pRxPacket,
548 NDIS_STATUS_FAILURE);
552 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
554 } else if (pRxD->U2M) {
556 (u16)((pRxWI->MCS) + (pRxWI->BW << 7) +
557 (pRxWI->ShortGI << 8) + (pRxWI->PHYMODE << 14));
560 pEntry = MacTableLookup(pAd, pHeader->Addr2);
562 Update_Rssi_Sample(pAd, &pEntry->RssiSample,
566 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
568 pAd->StaCfg.LastSNR0 = (u8)(pRxWI->SNR0);
569 pAd->StaCfg.LastSNR1 = (u8)(pRxWI->SNR1);
571 pAd->RalinkCounters.OneSecRxOkDataCnt++;
573 if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0))) {
574 /* re-assemble the fragmented packets */
575 /* return complete frame (pRxPacket) or NULL */
577 pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk);
581 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
583 /* process complete frame */
584 if (bFragment && (pRxD->Decrypted)
585 && (pEntry->WepStatus ==
586 Ndis802_11Encryption2Enabled)) {
587 /* Minus MIC length */
588 pRxBlk->DataSize -= 8;
590 /* For TKIP frame, calculate the MIC value */
591 if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) ==
597 STARxDataFrameAnnounce(pAd, pEntry, pRxBlk,
602 /* because RTMPDeFragmentDataFrame() will release rx packet, */
603 /* if packet is fragmented */
610 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
613 void STAHandleRxMgmtFrame(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk)
615 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
616 struct rt_rxwi * pRxWI = pRxBlk->pRxWI;
617 struct rt_header_802_11 * pHeader = pRxBlk->pHeader;
618 void *pRxPacket = pRxBlk->pRxPacket;
622 /* check if need to resend PS Poll when received packet with MoreData = 1 */
623 if ((pAd->StaCfg.Psm == PWR_SAVE)
624 && (pHeader->FC.MoreData == 1)) {
625 /* for UAPSD, all management frames will be VO priority */
626 if (pAd->CommonCfg.bAPSDAC_VO == 0) {
627 /* non-UAPSD delivery-enabled AC */
628 RTMP_PS_POLL_ENQUEUE(pAd);
632 /* TODO: if MoreData == 0, station can go to sleep */
634 /* We should collect RSSI not only U2M data but also my beacon */
635 if ((pHeader->FC.SubType == SUBTYPE_BEACON)
636 && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2))
637 && (pAd->RxAnt.EvaluatePeriod == 0)) {
638 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
640 pAd->StaCfg.LastSNR0 = (u8)(pRxWI->SNR0);
641 pAd->StaCfg.LastSNR1 = (u8)(pRxWI->SNR1);
644 /* First check the size, it MUST not exceed the mlme queue size */
645 if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE) {
646 DBGPRINT_ERR(("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount));
650 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader,
651 pRxWI->MPDUtotalByteCount,
652 pRxWI->RSSI0, pRxWI->RSSI1,
653 pRxWI->RSSI2, pRxD->PlcpSignal);
656 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
659 void STAHandleRxControlFrame(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk)
661 struct rt_rxwi * pRxWI = pRxBlk->pRxWI;
662 struct rt_header_802_11 * pHeader = pRxBlk->pHeader;
663 void *pRxPacket = pRxBlk->pRxPacket;
665 switch (pHeader->FC.SubType) {
666 case SUBTYPE_BLOCK_ACK_REQ:
668 CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID,
669 (pRxWI->MPDUtotalByteCount),
670 (struct rt_frame_ba_req *) pHeader);
673 case SUBTYPE_BLOCK_ACK:
679 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
683 ========================================================================
686 Process RxDone interrupt, running in DPC level
689 pAd Pointer to our adapter
694 IRQL = DISPATCH_LEVEL
697 This routine has to maintain Rx ring read pointer.
698 Need to consider QOS DATA format when converting to 802.3
699 ========================================================================
701 BOOLEAN STARxDoneInterruptHandle(struct rt_rtmp_adapter *pAd, IN BOOLEAN argc)
704 u32 RxProcessed, RxPending;
705 BOOLEAN bReschedule = FALSE;
706 PRT28XX_RXD_STRUC pRxD;
708 struct rt_rxwi * pRxWI;
710 struct rt_header_802_11 * pHeader;
711 struct rt_rx_blk RxCell;
713 RxProcessed = RxPending = 0;
715 /* process whole rx ring */
718 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF |
719 fRTMP_ADAPTER_RESET_IN_PROGRESS |
720 fRTMP_ADAPTER_HALT_IN_PROGRESS |
721 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
722 !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) {
726 if (RxProcessed++ > MAX_RX_PROCESS_CNT) {
727 /* need to reschedule rx handle */
731 #endif /* RTMP_MAC_PCI // */
733 RxProcessed++; /* test */
735 /* 1. allocate a new data packet into rx ring to replace received packet */
736 /* then processing the received packet */
737 /* 2. the callee must take charge of release of packet */
738 /* 3. As far as driver is concerned , */
739 /* the rx packet must */
740 /* a. be indicated to upper layer or */
741 /* b. be released if it is discarded */
743 GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule,
745 if (pRxPacket == NULL) {
746 /* no more packet to process */
749 /* get rx ring descriptor */
750 pRxD = &(RxCell.RxD);
751 /* get rx data buffer */
752 pData = GET_OS_PKT_DATAPTR(pRxPacket);
753 pRxWI = (struct rt_rxwi *) pData;
754 pHeader = (struct rt_header_802_11 *) (pData + RXWI_SIZE);
757 RxCell.pRxWI = pRxWI;
758 RxCell.pHeader = pHeader;
759 RxCell.pRxPacket = pRxPacket;
760 RxCell.pData = (u8 *) pHeader;
761 RxCell.DataSize = pRxWI->MPDUtotalByteCount;
764 /* Increase Total receive byte counter after real data received no mater any error or not */
765 pAd->RalinkCounters.ReceivedByteCount +=
766 pRxWI->MPDUtotalByteCount;
767 pAd->RalinkCounters.OneSecReceivedByteCount +=
768 pRxWI->MPDUtotalByteCount;
769 pAd->RalinkCounters.RxCount++;
771 INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount);
773 if (pRxWI->MPDUtotalByteCount < 14)
774 Status = NDIS_STATUS_FAILURE;
776 if (MONITOR_ON(pAd)) {
777 send_monitor_packets(pAd, &RxCell);
781 /* STARxDoneInterruptHandle() is called in rtusb_bulk.c */
783 /* Check for all RxD errors */
784 Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD);
786 /* Handle the received frame */
787 if (Status == NDIS_STATUS_SUCCESS) {
788 switch (pHeader->FC.Type) {
789 /* CASE I, receive a DATA frame */
792 /* process DATA frame */
793 STAHandleRxDataFrame(pAd, &RxCell);
796 /* CASE II, receive a MGMT frame */
799 STAHandleRxMgmtFrame(pAd, &RxCell);
802 /* CASE III. receive a CNTL frame */
805 STAHandleRxControlFrame(pAd, &RxCell);
808 /* discard other type */
810 RELEASE_NDIS_PACKET(pAd, pRxPacket,
811 NDIS_STATUS_FAILURE);
815 pAd->Counters8023.RxErrors++;
816 /* discard this frame */
817 RELEASE_NDIS_PACKET(pAd, pRxPacket,
818 NDIS_STATUS_FAILURE);
826 ========================================================================
830 pAd Pointer to our adapter
832 IRQL = DISPATCH_LEVEL
834 ========================================================================
836 void RTMPHandleTwakeupInterrupt(struct rt_rtmp_adapter *pAd)
838 AsicForceWakeup(pAd, FALSE);
842 ========================================================================
844 Early checking and OS-depened parsing for Tx packet send to our STA driver.
847 void * MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd.
848 void ** ppPacketArray The packet array need to do transmission.
849 u32 NumberOfPackets Number of packet in packet array.
855 This function do early checking and classification for send-out packet.
856 You only can put OS-depened & STA related code in here.
857 ========================================================================
859 void STASendPackets(void *MiniportAdapterContext,
860 void **ppPacketArray, u32 NumberOfPackets)
863 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)MiniportAdapterContext;
865 BOOLEAN allowToSend = FALSE;
867 for (Index = 0; Index < NumberOfPackets; Index++) {
868 pPacket = ppPacketArray[Index];
871 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)
872 || RTMP_TEST_FLAG(pAd,
873 fRTMP_ADAPTER_HALT_IN_PROGRESS)
874 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) {
875 /* Drop send request since hardware is in reset state */
877 } else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd)) {
878 /* Drop send request since there are no physical connection yet */
881 /* Record that orignal packet source is from NDIS layer,so that */
882 /* later on driver knows how to release this NDIS PACKET */
883 RTMP_SET_PACKET_WCID(pPacket, 0); /* this field is useless when in STA mode */
884 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
885 NDIS_SET_PACKET_STATUS(pPacket,
886 NDIS_STATUS_PENDING);
887 pAd->RalinkCounters.PendingNdisPacketCount++;
893 if (allowToSend == TRUE)
894 STASendPacket(pAd, pPacket);
896 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
899 /* Dequeue outgoing frames from TxSwQueue[] and process it */
900 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
905 ========================================================================
907 This routine is used to do packet parsing and classification for Tx packet
908 to STA device, and it will en-queue packets to our TxSwQueue depends on AC
912 pAd Pointer to our adapter
913 pPacket Pointer to send packet
916 NDIS_STATUS_SUCCESS If success to queue the packet into TxSwQueue.
917 NDIS_STATUS_FAILURE If failed to do en-queue.
920 You only can put OS-indepened & STA related code in here.
921 ========================================================================
923 int STASendPacket(struct rt_rtmp_adapter *pAd, void *pPacket)
925 struct rt_packet_info PacketInfo;
931 u8 QueIdx, UserPriority;
932 struct rt_mac_table_entry *pEntry = NULL;
933 unsigned int IrqFlags;
937 /* Prepare packet information structure for buffer descriptor */
938 /* chained within a single NDIS packet. */
939 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
941 if (pSrcBufVA == NULL) {
942 DBGPRINT(RT_DEBUG_ERROR,
943 ("STASendPacket --> pSrcBufVA == NULL !SrcBufLen=%x\n",
945 /* Resourece is low, system did not allocate virtual address */
946 /* return NDIS_STATUS_FAILURE directly to upper layer */
947 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
948 return NDIS_STATUS_FAILURE;
951 if (SrcBufLen < 14) {
952 DBGPRINT(RT_DEBUG_ERROR,
953 ("STASendPacket --> Ndis Packet buffer error!\n"));
954 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
955 return (NDIS_STATUS_FAILURE);
957 /* In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry. */
958 /* Note multicast packets in adhoc also use BSSID_WCID index. */
962 pEntry = &pAd->MacTab.Content[BSSID_WCID];
963 RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID);
964 Rate = pAd->CommonCfg.TxRate;
966 } else if (ADHOC_ON(pAd)) {
967 if (*pSrcBufVA & 0x01) {
968 RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID);
969 pEntry = &pAd->MacTab.Content[MCAST_WCID];
971 pEntry = MacTableLookup(pAd, pSrcBufVA);
973 Rate = pAd->CommonCfg.TxRate;
978 DBGPRINT(RT_DEBUG_ERROR,
979 ("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n",
980 PRINT_MAC(pSrcBufVA)));
981 /* Resourece is low, system did not allocate virtual address */
982 /* return NDIS_STATUS_FAILURE directly to upper layer */
983 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
984 return NDIS_STATUS_FAILURE;
989 RTMP_SET_PACKET_WCID(pPacket, (u8)pEntry->Aid);
992 /* Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags. */
993 /* Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL). */
994 RTMPCheckEtherType(pAd, pPacket);
997 /* WPA 802.1x secured port control - drop all non-802.1x frame before port secured */
999 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1000 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1001 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1002 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1003 || (pAd->StaCfg.IEEE8021X == TRUE)
1005 && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)
1006 || (pAd->StaCfg.MicErrCnt >= 2))
1007 && (RTMP_GET_PACKET_EAPOL(pPacket) == FALSE)
1009 DBGPRINT(RT_DEBUG_TRACE,
1010 ("STASendPacket --> Drop packet before port secured!\n"));
1011 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1013 return (NDIS_STATUS_FAILURE);
1016 /* STEP 1. Decide number of fragments required to deliver this MSDU. */
1017 /* The estimation here is not very accurate because difficult to */
1018 /* take encryption overhead into consideration here. The result */
1019 /* "NumberOfFrag" is then just used to pre-check if enough free */
1020 /* TXD are available to hold this MSDU. */
1022 if (*pSrcBufVA & 0x01) /* fragmentation not allowed on multicast & broadcast */
1024 else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))
1025 NumberOfFrag = 1; /* Aggregation overwhelms fragmentation */
1026 else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED))
1027 NumberOfFrag = 1; /* Aggregation overwhelms fragmentation */
1028 else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX)
1029 || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD))
1030 NumberOfFrag = 1; /* MIMO RATE overwhelms fragmentation */
1032 /* The calculated "NumberOfFrag" is a rough estimation because of various */
1033 /* encryption/encapsulation overhead not taken into consideration. This number is just */
1034 /* used to make sure enough free TXD are available before fragmentation takes place. */
1035 /* In case the actual required number of fragments of an NDIS packet */
1036 /* excceeds "NumberOfFrag"caculated here and not enough free TXD available, the */
1037 /* last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of */
1038 /* resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should */
1039 /* rarely happen and the penalty is just like a TX RETRY fail. Affordable. */
1042 (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 -
1045 ((PacketInfo.TotalPacketLength - LENGTH_802_3 +
1046 LENGTH_802_1_H) / AllowFragSize) + 1;
1047 /* To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size */
1048 if (((PacketInfo.TotalPacketLength - LENGTH_802_3 +
1049 LENGTH_802_1_H) % AllowFragSize) == 0) {
1054 /* Save fragment number to Ndis packet reserved field */
1055 RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
1057 /* STEP 2. Check the requirement of RTS: */
1058 /* If multiple fragment required, RTS is required only for the first fragment */
1059 /* if the fragment size large than RTS threshold */
1060 /* For RT28xx, Let ASIC send RTS/CTS */
1061 /* RTMP_SET_PACKET_RTS(pPacket, 0); */
1062 if (NumberOfFrag > 1)
1064 (pAd->CommonCfg.FragmentThreshold >
1065 pAd->CommonCfg.RtsThreshold) ? 1 : 0;
1068 (PacketInfo.TotalPacketLength >
1069 pAd->CommonCfg.RtsThreshold) ? 1 : 0;
1071 /* Save RTS requirement to Ndis packet reserved field */
1072 RTMP_SET_PACKET_RTS(pPacket, RTSRequired);
1073 RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate);
1076 /* STEP 3. Traffic classification. outcome = <UserPriority, QueIdx> */
1080 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
1081 CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE)) {
1083 u8 LlcSnapLen = 0, Byte0, Byte1;
1085 /* get Ethernet protocol field */
1087 (u16)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
1088 if (Protocol <= 1500) {
1089 /* get Ethernet protocol field from LLC/SNAP */
1090 if (Sniff2BytesFromNdisBuffer
1091 (PacketInfo.pFirstBuffer, LENGTH_802_3 + 6,
1092 &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1095 Protocol = (u16)((Byte0 << 8) + Byte1);
1098 /* always AC_BE for non-IP packet */
1099 if (Protocol != 0x0800)
1103 if (Sniff2BytesFromNdisBuffer
1104 (PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen,
1105 &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1108 /* return AC_BE if packet is not IPv4 */
1109 if ((Byte0 & 0xf0) != 0x40)
1113 UserPriority = (Byte1 & 0xe0) >> 5;
1114 QueIdx = MapUserPriorityToAccessCategory[UserPriority];
1116 /* TODO: have to check ACM bit. apply TSPEC if ACM is ON */
1117 /* TODO: downgrade UP & QueIdx before passing ACM */
1119 Under WMM ACM control, we dont need to check the bit;
1120 Or when a TSPEC is built for VO but we will change to issue
1121 BA session for BE here, so we will not use BA to send VO packets.
1123 if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx]) {
1130 RTMP_SET_PACKET_UP(pPacket, UserPriority);
1132 /* Make sure SendTxWait queue resource won't be used by other threads */
1133 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1134 if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE) {
1135 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1136 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1138 return NDIS_STATUS_FAILURE;
1140 InsertTailQueueAc(pAd, pEntry, &pAd->TxSwQueue[QueIdx],
1141 PACKET_TO_QUEUE_ENTRY(pPacket));
1143 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1145 if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE) &&
1146 IS_HT_STA(pEntry)) {
1147 /*struct rt_mac_table_entry *pMacEntry = &pAd->MacTab.Content[BSSID_WCID]; */
1148 if (((pEntry->TXBAbitmap & (1 << UserPriority)) == 0) &&
1149 ((pEntry->BADeclineBitmap & (1 << UserPriority)) == 0) &&
1150 (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
1151 /* For IOT compatibility, if */
1152 /* 1. It is Ralink chip or */
1153 /* 2. It is OPEN or AES mode, */
1154 /* then BA session can be bulit. */
1155 && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0)
1156 || (pEntry->WepStatus != Ndis802_11WEPEnabled
1157 && pEntry->WepStatus !=
1158 Ndis802_11Encryption2Enabled))
1160 BAOriSessionSetUp(pAd, pEntry, UserPriority, 0, 10,
1165 pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; /* TODO: for debug only. to be removed */
1166 return NDIS_STATUS_SUCCESS;
1170 ========================================================================
1172 Routine Description:
1173 This subroutine will scan through releative ring descriptor to find
1174 out avaliable free ring descriptor and compare with request size.
1177 pAd Pointer to our adapter
1178 QueIdx Selected TX Ring
1181 NDIS_STATUS_FAILURE Not enough free descriptor
1182 NDIS_STATUS_SUCCESS Enough free descriptor
1184 IRQL = PASSIVE_LEVEL
1185 IRQL = DISPATCH_LEVEL
1189 ========================================================================
1192 int RTMPFreeTXDRequest(struct rt_rtmp_adapter *pAd,
1194 u8 NumberRequired, u8 *FreeNumberIs)
1196 unsigned long FreeNumber = 0;
1197 int Status = NDIS_STATUS_FAILURE;
1204 if (pAd->TxRing[QueIdx].TxSwFreeIdx >
1205 pAd->TxRing[QueIdx].TxCpuIdx)
1207 pAd->TxRing[QueIdx].TxSwFreeIdx -
1208 pAd->TxRing[QueIdx].TxCpuIdx - 1;
1211 pAd->TxRing[QueIdx].TxSwFreeIdx + TX_RING_SIZE -
1212 pAd->TxRing[QueIdx].TxCpuIdx - 1;
1214 if (FreeNumber >= NumberRequired)
1215 Status = NDIS_STATUS_SUCCESS;
1219 if (pAd->MgmtRing.TxSwFreeIdx > pAd->MgmtRing.TxCpuIdx)
1221 pAd->MgmtRing.TxSwFreeIdx - pAd->MgmtRing.TxCpuIdx -
1225 pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE -
1226 pAd->MgmtRing.TxCpuIdx - 1;
1228 if (FreeNumber >= NumberRequired)
1229 Status = NDIS_STATUS_SUCCESS;
1233 DBGPRINT(RT_DEBUG_ERROR,
1234 ("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1237 *FreeNumberIs = (u8)FreeNumber;
1241 #endif /* RTMP_MAC_PCI // */
1244 Actually, this function used to check if the TxHardware Queue still has frame need to send.
1245 If no frame need to send, go to sleep, else, still wake up.
1247 int RTMPFreeTXDRequest(struct rt_rtmp_adapter *pAd,
1249 u8 NumberRequired, u8 *FreeNumberIs)
1251 /*unsigned long FreeNumber = 0; */
1252 int Status = NDIS_STATUS_FAILURE;
1253 unsigned long IrqFlags;
1254 struct rt_ht_tx_context *pHTTXContext;
1262 pHTTXContext = &pAd->TxContext[QueIdx];
1263 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx],
1265 if ((pHTTXContext->CurWritePosition !=
1266 pHTTXContext->ENextBulkOutPosition)
1267 || (pHTTXContext->IRPPending == TRUE)) {
1268 Status = NDIS_STATUS_FAILURE;
1270 Status = NDIS_STATUS_SUCCESS;
1272 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx],
1277 if (pAd->MgmtRing.TxSwFreeIdx != MGMT_RING_SIZE)
1278 Status = NDIS_STATUS_FAILURE;
1280 Status = NDIS_STATUS_SUCCESS;
1283 DBGPRINT(RT_DEBUG_ERROR,
1284 ("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1290 #endif /* RTMP_MAC_USB // */
1292 void RTMPSendDisassociationFrame(struct rt_rtmp_adapter *pAd)
1296 void RTMPSendNullFrame(struct rt_rtmp_adapter *pAd,
1297 u8 TxRate, IN BOOLEAN bQosNull)
1300 unsigned long Length;
1301 struct rt_header_802_11 * pHeader_802_11;
1303 /* WPA 802.1x secured port control */
1304 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1305 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1306 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1307 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1308 || (pAd->StaCfg.IEEE8021X == TRUE)
1309 ) && (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) {
1313 NdisZeroMemory(NullFrame, 48);
1314 Length = sizeof(struct rt_header_802_11);
1316 pHeader_802_11 = (struct rt_header_802_11 *) NullFrame;
1318 pHeader_802_11->FC.Type = BTYPE_DATA;
1319 pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
1320 pHeader_802_11->FC.ToDs = 1;
1321 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1322 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1323 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1325 if (pAd->CommonCfg.bAPSDForcePowerSave) {
1326 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1328 pHeader_802_11->FC.PwrMgmt =
1329 (pAd->StaCfg.Psm == PWR_SAVE) ? 1 : 0;
1331 pHeader_802_11->Duration =
1332 pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
1335 pHeader_802_11->Sequence = pAd->Sequence;
1337 /* Prepare QosNull function frame */
1339 pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
1341 /* copy QOS control bytes */
1342 NullFrame[Length] = 0;
1343 NullFrame[Length + 1] = 0;
1344 Length += 2; /* if pad with 2 bytes for alignment, APSD will fail */
1347 HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
1351 /* IRQL = DISPATCH_LEVEL */
1352 void RTMPSendRTSFrame(struct rt_rtmp_adapter *pAd,
1354 IN unsigned int NextMpduSize,
1357 u16 AckDuration, u8 QueIdx, u8 FrameGap)
1361 /* -------------------------------------------------------- */
1362 /* FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM */
1363 /* Find the WPA key, either Group or Pairwise Key */
1364 /* LEAP + TKIP also use WPA key. */
1365 /* -------------------------------------------------------- */
1366 /* Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst */
1367 /* In Cisco CCX 2.0 Leap Authentication */
1368 /* WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey */
1369 /* Instead of the SharedKey, SharedKey Length may be Zero. */
1370 void STAFindCipherAlgorithm(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
1372 NDIS_802_11_ENCRYPTION_STATUS Cipher; /* To indicate cipher used for this packet */
1373 u8 CipherAlg = CIPHER_NONE; /* cipher alogrithm */
1376 struct rt_cipher_key *pKey = NULL;
1378 pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
1382 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1383 Cipher = pAd->StaCfg.GroupCipher; /* Cipher for Multicast or Broadcast */
1385 Cipher = pAd->StaCfg.PairCipher; /* Cipher for Unicast */
1387 if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket)) {
1388 ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <=
1391 /* 4-way handshaking frame must be clear */
1392 if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame))
1393 && (pAd->SharedKey[BSS0][0].CipherAlg)
1394 && (pAd->SharedKey[BSS0][0].KeyLen)) {
1395 CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1398 } else if (Cipher == Ndis802_11Encryption1Enabled) {
1399 KeyIdx = pAd->StaCfg.DefaultKeyId;
1400 } else if ((Cipher == Ndis802_11Encryption2Enabled) ||
1401 (Cipher == Ndis802_11Encryption3Enabled)) {
1402 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) /* multicast */
1403 KeyIdx = pAd->StaCfg.DefaultKeyId;
1404 else if (pAd->SharedKey[BSS0][0].KeyLen)
1407 KeyIdx = pAd->StaCfg.DefaultKeyId;
1411 CipherAlg = CIPHER_NONE;
1412 else if ((Cipher == Ndis802_11EncryptionDisabled)
1413 || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
1414 CipherAlg = CIPHER_NONE;
1415 else if (pAd->StaCfg.WpaSupplicantUP &&
1416 (Cipher == Ndis802_11Encryption1Enabled) &&
1417 (pAd->StaCfg.IEEE8021X == TRUE) &&
1418 (pAd->StaCfg.PortSecured ==
1419 WPA_802_1X_PORT_NOT_SECURED))
1420 CipherAlg = CIPHER_NONE;
1422 /*Header_802_11.FC.Wep = 1; */
1423 CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
1424 pKey = &pAd->SharedKey[BSS0][KeyIdx];
1428 pTxBlk->CipherAlg = CipherAlg;
1429 pTxBlk->pKey = pKey;
1432 void STABuildCommon802_11Header(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
1434 struct rt_header_802_11 *pHeader_802_11;
1437 /* MAKE A COMMON 802.11 HEADER */
1440 /* normal wlan header size : 24 octets */
1441 pTxBlk->MpduHeaderLen = sizeof(struct rt_header_802_11);
1444 (struct rt_header_802_11 *) & pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1446 NdisZeroMemory(pHeader_802_11, sizeof(struct rt_header_802_11));
1448 pHeader_802_11->FC.FrDs = 0;
1449 pHeader_802_11->FC.Type = BTYPE_DATA;
1450 pHeader_802_11->FC.SubType =
1451 ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA :
1454 if (pTxBlk->pMacEntry) {
1455 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS)) {
1456 pHeader_802_11->Sequence =
1457 pTxBlk->pMacEntry->NonQosDataSeq;
1458 pTxBlk->pMacEntry->NonQosDataSeq =
1459 (pTxBlk->pMacEntry->NonQosDataSeq + 1) & MAXSEQ;
1462 pHeader_802_11->Sequence =
1463 pTxBlk->pMacEntry->TxSeq[pTxBlk->
1465 pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] =
1466 (pTxBlk->pMacEntry->
1467 TxSeq[pTxBlk->UserPriority] + 1) & MAXSEQ;
1471 pHeader_802_11->Sequence = pAd->Sequence;
1472 pAd->Sequence = (pAd->Sequence + 1) & MAXSEQ; /* next sequence */
1475 pHeader_802_11->Frag = 0;
1477 pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1480 if (INFRA_ON(pAd)) {
1482 COPY_MAC_ADDR(pHeader_802_11->Addr1,
1483 pAd->CommonCfg.Bssid);
1484 COPY_MAC_ADDR(pHeader_802_11->Addr2,
1485 pAd->CurrentAddress);
1486 COPY_MAC_ADDR(pHeader_802_11->Addr3,
1487 pTxBlk->pSrcBufHeader);
1488 pHeader_802_11->FC.ToDs = 1;
1490 } else if (ADHOC_ON(pAd)) {
1491 COPY_MAC_ADDR(pHeader_802_11->Addr1,
1492 pTxBlk->pSrcBufHeader);
1493 COPY_MAC_ADDR(pHeader_802_11->Addr2,
1494 pAd->CurrentAddress);
1495 COPY_MAC_ADDR(pHeader_802_11->Addr3,
1496 pAd->CommonCfg.Bssid);
1497 pHeader_802_11->FC.ToDs = 0;
1501 if (pTxBlk->CipherAlg != CIPHER_NONE)
1502 pHeader_802_11->FC.Wep = 1;
1504 /* ----------------------------------------------------------------- */
1505 /* STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later. */
1506 /* ----------------------------------------------------------------- */
1507 if (pAd->CommonCfg.bAPSDForcePowerSave)
1508 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1510 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1513 void STABuildCache802_11Header(struct rt_rtmp_adapter *pAd,
1514 struct rt_tx_blk *pTxBlk, u8 * pHeader)
1516 struct rt_mac_table_entry *pMacEntry;
1517 struct rt_header_802_11 * pHeader80211;
1519 pHeader80211 = (struct rt_header_802_11 *) pHeader;
1520 pMacEntry = pTxBlk->pMacEntry;
1523 /* Update the cached 802.11 HEADER */
1526 /* normal wlan header size : 24 octets */
1527 pTxBlk->MpduHeaderLen = sizeof(struct rt_header_802_11);
1530 pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1533 pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
1534 pMacEntry->TxSeq[pTxBlk->UserPriority] =
1535 (pMacEntry->TxSeq[pTxBlk->UserPriority] + 1) & MAXSEQ;
1538 /* Check if the frame can be sent through DLS direct link interface */
1539 /* If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability) */
1541 /* The addr3 of normal packet send from DS is Dest Mac address. */
1543 COPY_MAC_ADDR(pHeader80211->Addr3,
1544 pAd->CommonCfg.Bssid);
1546 COPY_MAC_ADDR(pHeader80211->Addr3,
1547 pTxBlk->pSrcBufHeader);
1550 /* ----------------------------------------------------------------- */
1551 /* STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later. */
1552 /* ----------------------------------------------------------------- */
1553 if (pAd->CommonCfg.bAPSDForcePowerSave)
1554 pHeader80211->FC.PwrMgmt = PWR_SAVE;
1556 pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1559 static inline u8 *STA_Build_ARalink_Frame_Header(struct rt_rtmp_adapter *pAd,
1560 struct rt_tx_blk *pTxBlk)
1563 struct rt_header_802_11 *pHeader_802_11;
1566 struct rt_queue_entry *pQEntry;
1568 STAFindCipherAlgorithm(pAd, pTxBlk);
1569 STABuildCommon802_11Header(pAd, pTxBlk);
1571 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1572 pHeader_802_11 = (struct rt_header_802_11 *) pHeaderBufPtr;
1574 /* steal "order" bit to mark "aggregation" */
1575 pHeader_802_11->FC.Order = 1;
1577 /* skip common header */
1578 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1580 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) {
1582 /* build QOS Control bytes */
1584 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1586 *(pHeaderBufPtr + 1) = 0;
1588 pTxBlk->MpduHeaderLen += 2;
1590 /* padding at front of LLC header. LLC header should at 4-bytes aligment. */
1591 pTxBlk->HdrPadLen = (unsigned long)pHeaderBufPtr;
1592 pHeaderBufPtr = (u8 *)ROUND_UP(pHeaderBufPtr, 4);
1593 pTxBlk->HdrPadLen = (unsigned long)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1595 /* For RA Aggregation, */
1596 /* put the 2nd MSDU length(extra 2-byte field) after struct rt_qos_control in little endian format */
1597 pQEntry = pTxBlk->TxPacketList.Head;
1598 pNextPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1599 nextBufLen = GET_OS_PKT_LEN(pNextPacket);
1600 if (RTMP_GET_PACKET_VLAN(pNextPacket))
1601 nextBufLen -= LENGTH_802_1Q;
1603 *pHeaderBufPtr = (u8)nextBufLen & 0xff;
1604 *(pHeaderBufPtr + 1) = (u8)(nextBufLen >> 8);
1607 pTxBlk->MpduHeaderLen += 2;
1609 return pHeaderBufPtr;
1613 static inline u8 *STA_Build_AMSDU_Frame_Header(struct rt_rtmp_adapter *pAd,
1614 struct rt_tx_blk *pTxBlk)
1616 u8 *pHeaderBufPtr; /*, pSaveBufPtr; */
1617 struct rt_header_802_11 *pHeader_802_11;
1619 STAFindCipherAlgorithm(pAd, pTxBlk);
1620 STABuildCommon802_11Header(pAd, pTxBlk);
1622 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1623 pHeader_802_11 = (struct rt_header_802_11 *) pHeaderBufPtr;
1625 /* skip common header */
1626 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1629 /* build QOS Control bytes */
1631 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1636 *pHeaderBufPtr |= 0x80;
1638 *(pHeaderBufPtr + 1) = 0;
1640 pTxBlk->MpduHeaderLen += 2;
1642 /*pSaveBufPtr = pHeaderBufPtr; */
1645 /* padding at front of LLC header */
1646 /* LLC header should locate at 4-octets aligment */
1648 /* @@@ MpduHeaderLen excluding padding @@@ */
1650 pTxBlk->HdrPadLen = (unsigned long)pHeaderBufPtr;
1651 pHeaderBufPtr = (u8 *)ROUND_UP(pHeaderBufPtr, 4);
1652 pTxBlk->HdrPadLen = (unsigned long)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1654 return pHeaderBufPtr;
1658 void STA_AMPDU_Frame_Tx(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
1660 struct rt_header_802_11 *pHeader_802_11;
1663 struct rt_mac_table_entry *pMacEntry;
1665 struct rt_queue_entry *pQEntry;
1669 while (pTxBlk->TxPacketList.Head) {
1670 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1671 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1672 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) {
1673 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket,
1674 NDIS_STATUS_FAILURE);
1679 (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1681 pMacEntry = pTxBlk->pMacEntry;
1682 if (pMacEntry->isCached) {
1683 /* NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]! */
1684 NdisMoveMemory((u8 *)& pTxBlk->
1685 HeaderBuf[TXINFO_SIZE],
1686 (u8 *)& pMacEntry->CachedBuf[0],
1687 TXWI_SIZE + sizeof(struct rt_header_802_11));
1690 HeaderBuf[TXINFO_SIZE + TXWI_SIZE]);
1691 STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
1693 STAFindCipherAlgorithm(pAd, pTxBlk);
1694 STABuildCommon802_11Header(pAd, pTxBlk);
1697 &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1700 pHeader_802_11 = (struct rt_header_802_11 *) pHeaderBufPtr;
1702 /* skip common header */
1703 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1706 /* build QOS Control bytes */
1708 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1709 *(pHeaderBufPtr + 1) = 0;
1711 pTxBlk->MpduHeaderLen += 2;
1715 /* HTC control filed following QoS field */
1717 if ((pAd->CommonCfg.bRdg == TRUE)
1718 && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry,
1719 fCLIENT_STATUS_RDG_CAPABLE)) {
1720 if (pMacEntry->isCached == FALSE) {
1722 pHeader_802_11->FC.Order = 1;
1724 NdisZeroMemory(pHeaderBufPtr, 4);
1725 *(pHeaderBufPtr + 3) |= 0x80;
1728 pTxBlk->MpduHeaderLen += 4;
1730 /*pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE; */
1731 ASSERT(pTxBlk->MpduHeaderLen >= 24);
1733 /* skip 802.3 header */
1734 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1735 pTxBlk->SrcBufLen -= LENGTH_802_3;
1739 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1740 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1743 /* padding at front of LLC header */
1744 /* LLC header should locate at 4-octets aligment */
1746 /* @@@ MpduHeaderLen excluding padding @@@ */
1748 pTxBlk->HdrPadLen = (unsigned long)pHeaderBufPtr;
1749 pHeaderBufPtr = (u8 *)ROUND_UP(pHeaderBufPtr, 4);
1750 pTxBlk->HdrPadLen = (unsigned long)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1755 /* Insert LLC-SNAP encapsulation - 8 octets */
1757 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->
1760 pExtraLlcSnapEncap);
1761 if (pTxBlk->pExtraLlcSnapEncap) {
1762 NdisMoveMemory(pHeaderBufPtr,
1763 pTxBlk->pExtraLlcSnapEncap, 6);
1765 /* get 2 octets (TypeofLen) */
1766 NdisMoveMemory(pHeaderBufPtr,
1767 pTxBlk->pSrcBufData - 2, 2);
1769 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1774 if (pMacEntry->isCached) {
1775 RTMPWriteTxWI_Cache(pAd,
1776 (struct rt_txwi *) (&pTxBlk->
1781 RTMPWriteTxWI_Data(pAd,
1782 (struct rt_txwi *) (&pTxBlk->
1787 NdisZeroMemory((u8 *)(&pMacEntry->CachedBuf[0]),
1788 sizeof(pMacEntry->CachedBuf));
1789 NdisMoveMemory((u8 *)(&pMacEntry->CachedBuf[0]),
1791 HeaderBuf[TXINFO_SIZE]),
1794 HeaderBuf[TXINFO_SIZE])));
1795 pMacEntry->isCached = TRUE;
1798 /* calculate Transmitted AMPDU count and ByteCount */
1800 pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.
1802 pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.
1803 QuadPart += pTxBlk->SrcBufLen;
1806 /*FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); */
1808 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1813 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
1814 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1816 pAd->RalinkCounters.KickTxCount++;
1817 pAd->RalinkCounters.OneSecTxDoneCount++;
1822 void STA_AMSDU_Frame_Tx(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
1826 u16 subFramePayloadLen = 0; /* AMSDU Subframe length without AMSDU-Header / Padding. */
1827 u16 totalMPDUSize = 0;
1830 u16 FirstTx = 0, LastTxIdx = 0;
1833 struct rt_queue_entry *pQEntry;
1837 ASSERT((pTxBlk->TxPacketList.Number > 1));
1839 while (pTxBlk->TxPacketList.Head) {
1840 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1841 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1842 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) {
1843 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket,
1844 NDIS_STATUS_FAILURE);
1849 (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1851 /* skip 802.3 header */
1852 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1853 pTxBlk->SrcBufLen -= LENGTH_802_3;
1857 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1858 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1861 if (frameNum == 0) {
1863 STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
1865 /* NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled. */
1866 RTMPWriteTxWI_Data(pAd,
1867 (struct rt_txwi *) (&pTxBlk->
1872 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
1874 ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD +
1876 4) - (LENGTH_AMSDU_SUBFRAMEHEAD +
1877 subFramePayloadLen);
1878 NdisZeroMemory(pHeaderBufPtr,
1879 padding + LENGTH_AMSDU_SUBFRAMEHEAD);
1880 pHeaderBufPtr += padding;
1881 pTxBlk->MpduHeaderLen = padding;
1885 /* A-MSDU subframe */
1886 /* DA(6)+SA(6)+Length(2) + LLC/SNAP Encap */
1888 subFrameHeader = pHeaderBufPtr;
1889 subFramePayloadLen = pTxBlk->SrcBufLen;
1891 NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
1893 pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
1894 pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
1897 /* Insert LLC-SNAP encapsulation - 8 octets */
1899 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData - 2,
1900 pTxBlk->pExtraLlcSnapEncap);
1902 subFramePayloadLen = pTxBlk->SrcBufLen;
1904 if (pTxBlk->pExtraLlcSnapEncap) {
1905 NdisMoveMemory(pHeaderBufPtr,
1906 pTxBlk->pExtraLlcSnapEncap, 6);
1908 /* get 2 octets (TypeofLen) */
1909 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData - 2,
1912 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1913 subFramePayloadLen += LENGTH_802_1_H;
1915 /* update subFrame Length field */
1916 subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
1917 subFrameHeader[13] = subFramePayloadLen & 0xFF;
1919 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1923 HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum,
1927 HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum,
1932 pAd->RalinkCounters.KickTxCount++;
1933 pAd->RalinkCounters.OneSecTxDoneCount++;
1935 /* calculate Transmitted AMSDU Count and ByteCount */
1937 pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart++;
1938 pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart +=
1944 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
1945 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
1950 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
1951 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1954 void STA_Legacy_Frame_Tx(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
1956 struct rt_header_802_11 *pHeader_802_11;
1960 struct rt_queue_entry *pQEntry;
1964 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1965 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1966 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) {
1967 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1971 if (pTxBlk->TxFrameType == TX_MCAST_FRAME) {
1972 INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
1975 if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
1976 TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
1978 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
1980 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1982 if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
1983 pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
1985 STAFindCipherAlgorithm(pAd, pTxBlk);
1986 STABuildCommon802_11Header(pAd, pTxBlk);
1988 /* skip 802.3 header */
1989 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1990 pTxBlk->SrcBufLen -= LENGTH_802_3;
1994 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1995 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1998 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1999 pHeader_802_11 = (struct rt_header_802_11 *) pHeaderBufPtr;
2001 /* skip common header */
2002 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2004 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) {
2006 /* build QOS Control bytes */
2009 ((pTxBlk->UserPriority & 0x0F) | (pAd->CommonCfg.
2012 *(pHeaderBufPtr + 1) = 0;
2014 pTxBlk->MpduHeaderLen += 2;
2016 /* The remaining content of MPDU header should locate at 4-octets aligment */
2017 pTxBlk->HdrPadLen = (unsigned long)pHeaderBufPtr;
2018 pHeaderBufPtr = (u8 *)ROUND_UP(pHeaderBufPtr, 4);
2019 pTxBlk->HdrPadLen = (unsigned long)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2024 /* Insert LLC-SNAP encapsulation - 8 octets */
2027 /* if original Ethernet frame contains no LLC/SNAP, */
2028 /* then an extra LLC/SNAP encap is required */
2030 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader,
2031 pTxBlk->pExtraLlcSnapEncap);
2032 if (pTxBlk->pExtraLlcSnapEncap) {
2035 NdisMoveMemory(pHeaderBufPtr,
2036 pTxBlk->pExtraLlcSnapEncap, 6);
2039 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2040 /* get 2 octets (TypeofLen) */
2041 NdisMoveMemory(pHeaderBufPtr,
2042 pTxBlk->pSrcBufHeader + 12 + vlan_size,
2045 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2051 /* prepare for TXWI */
2052 /* use Wcid as Key Index */
2055 RTMPWriteTxWI_Data(pAd, (struct rt_txwi *) (&pTxBlk->HeaderBuf[TXINFO_SIZE]),
2058 /*FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); */
2060 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
2062 pAd->RalinkCounters.KickTxCount++;
2063 pAd->RalinkCounters.OneSecTxDoneCount++;
2068 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2069 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2072 void STA_ARalink_Frame_Tx(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
2076 u16 totalMPDUSize = 0;
2077 u16 FirstTx, LastTxIdx;
2080 struct rt_queue_entry *pQEntry;
2084 ASSERT((pTxBlk->TxPacketList.Number == 2));
2086 FirstTx = LastTxIdx = 0; /* Is it ok init they as 0? */
2087 while (pTxBlk->TxPacketList.Head) {
2088 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2089 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2091 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) {
2092 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket,
2093 NDIS_STATUS_FAILURE);
2098 (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2100 /* skip 802.3 header */
2101 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2102 pTxBlk->SrcBufLen -= LENGTH_802_3;
2106 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2107 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2110 if (frameNum == 0) { /* For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header */
2113 STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
2115 /* It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount */
2116 /* will be updated after final frame was handled. */
2117 RTMPWriteTxWI_Data(pAd,
2118 (struct rt_txwi *) (&pTxBlk->
2124 /* Insert LLC-SNAP encapsulation - 8 octets */
2126 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->
2129 pExtraLlcSnapEncap);
2131 if (pTxBlk->pExtraLlcSnapEncap) {
2132 NdisMoveMemory(pHeaderBufPtr,
2133 pTxBlk->pExtraLlcSnapEncap, 6);
2135 /* get 2 octets (TypeofLen) */
2136 NdisMoveMemory(pHeaderBufPtr,
2137 pTxBlk->pSrcBufData - 2, 2);
2139 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2141 } else { /* For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0. */
2143 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
2144 pTxBlk->MpduHeaderLen = 0;
2146 /* A-Ralink sub-sequent frame header is the same as 802.3 header. */
2147 /* DA(6)+SA(6)+FrameType(2) */
2148 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader,
2150 pHeaderBufPtr += 12;
2151 /* get 2 octets (TypeofLen) */
2152 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData - 2,
2155 pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD;
2158 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2160 /*FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); */
2163 HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum,
2167 HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum,
2172 pAd->RalinkCounters.OneSecTxAggregationCount++;
2173 pAd->RalinkCounters.KickTxCount++;
2174 pAd->RalinkCounters.OneSecTxDoneCount++;
2178 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2179 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2184 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2185 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2189 void STA_Fragment_Frame_Tx(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
2191 struct rt_header_802_11 *pHeader_802_11;
2195 struct rt_packet_info PacketInfo;
2196 u16 EncryptionOverhead = 0;
2197 u32 FreeMpduSize, SrcRemainingBytes;
2201 struct rt_queue_entry *pQEntry;
2202 HTTRANSMIT_SETTING *pTransmit;
2206 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2207 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2208 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) {
2209 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2213 ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag));
2214 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2216 STAFindCipherAlgorithm(pAd, pTxBlk);
2217 STABuildCommon802_11Header(pAd, pTxBlk);
2219 if (pTxBlk->CipherAlg == CIPHER_TKIP) {
2221 duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket);
2222 if (pTxBlk->pPacket == NULL)
2224 RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo,
2225 &pTxBlk->pSrcBufHeader,
2226 &pTxBlk->SrcBufLen);
2228 /* skip 802.3 header */
2229 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2230 pTxBlk->SrcBufLen -= LENGTH_802_3;
2234 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2235 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2238 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2239 pHeader_802_11 = (struct rt_header_802_11 *) pHeaderBufPtr;
2241 /* skip common header */
2242 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2244 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) {
2246 /* build QOS Control bytes */
2248 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2250 *(pHeaderBufPtr + 1) = 0;
2252 pTxBlk->MpduHeaderLen += 2;
2255 /* padding at front of LLC header */
2256 /* LLC header should locate at 4-octets aligment */
2258 pTxBlk->HdrPadLen = (unsigned long)pHeaderBufPtr;
2259 pHeaderBufPtr = (u8 *)ROUND_UP(pHeaderBufPtr, 4);
2260 pTxBlk->HdrPadLen = (unsigned long)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2263 /* Insert LLC-SNAP encapsulation - 8 octets */
2266 /* if original Ethernet frame contains no LLC/SNAP, */
2267 /* then an extra LLC/SNAP encap is required */
2269 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader,
2270 pTxBlk->pExtraLlcSnapEncap);
2271 if (pTxBlk->pExtraLlcSnapEncap) {
2274 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2277 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2278 /* get 2 octets (TypeofLen) */
2279 NdisMoveMemory(pHeaderBufPtr,
2280 pTxBlk->pSrcBufHeader + 12 + vlan_size, 2);
2282 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2285 /* If TKIP is used and fragmentation is required. Driver has to */
2286 /* append TKIP MIC at tail of the scatter buffer */
2287 /* MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC */
2288 if (pTxBlk->CipherAlg == CIPHER_TKIP) {
2289 RTMPCalculateMICValue(pAd, pTxBlk->pPacket,
2290 pTxBlk->pExtraLlcSnapEncap, pTxBlk->pKey,
2293 /* NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust */
2294 /* to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress. */
2295 NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen,
2296 &pAd->PrivateInfo.Tx.MIC[0], 8);
2297 /*skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8); */
2298 pTxBlk->SrcBufLen += 8;
2299 pTxBlk->TotalFrameLen += 8;
2300 pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC;
2303 /* calcuate the overhead bytes that encryption algorithm may add. This */
2304 /* affects the calculate of "duration" field */
2306 if ((pTxBlk->CipherAlg == CIPHER_WEP64)
2307 || (pTxBlk->CipherAlg == CIPHER_WEP128))
2308 EncryptionOverhead = 8; /*WEP: IV[4] + ICV[4]; */
2309 else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC)
2310 EncryptionOverhead = 12; /*TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength */
2311 else if (pTxBlk->CipherAlg == CIPHER_TKIP)
2312 EncryptionOverhead = 20; /*TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8] */
2313 else if (pTxBlk->CipherAlg == CIPHER_AES)
2314 EncryptionOverhead = 16; /* AES: IV[4] + EIV[4] + MIC[8] */
2316 EncryptionOverhead = 0;
2318 pTransmit = pTxBlk->pTransmit;
2319 /* Decide the TX rate */
2320 if (pTransmit->field.MODE == MODE_CCK)
2321 pTxBlk->TxRate = pTransmit->field.MCS;
2322 else if (pTransmit->field.MODE == MODE_OFDM)
2323 pTxBlk->TxRate = pTransmit->field.MCS + RATE_FIRST_OFDM_RATE;
2325 pTxBlk->TxRate = RATE_6_5;
2327 /* decide how much time an ACK/CTS frame will consume in the air */
2328 if (pTxBlk->TxRate <= RATE_LAST_OFDM_RATE)
2330 RTMPCalcDuration(pAd,
2331 pAd->CommonCfg.ExpectedACKRate[pTxBlk->
2335 AckDuration = RTMPCalcDuration(pAd, RATE_6_5, 14);
2337 /* Init the total payload length of this frame. */
2338 SrcRemainingBytes = pTxBlk->SrcBufLen;
2340 pTxBlk->TotalFragNum = 0xff;
2344 FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC;
2346 FreeMpduSize -= pTxBlk->MpduHeaderLen;
2348 if (SrcRemainingBytes <= FreeMpduSize) { /* this is the last or only fragment */
2350 pTxBlk->SrcBufLen = SrcRemainingBytes;
2352 pHeader_802_11->FC.MoreFrag = 0;
2353 pHeader_802_11->Duration =
2354 pAd->CommonCfg.Dsifs + AckDuration;
2356 /* Indicate the lower layer that this's the last fragment. */
2357 pTxBlk->TotalFragNum = fragNum;
2358 } else { /* more fragment is required */
2360 pTxBlk->SrcBufLen = FreeMpduSize;
2363 min(((u32)SrcRemainingBytes - pTxBlk->SrcBufLen),
2364 ((u32)pAd->CommonCfg.FragmentThreshold));
2365 pHeader_802_11->FC.MoreFrag = 1;
2366 pHeader_802_11->Duration =
2367 (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) +
2368 RTMPCalcDuration(pAd, pTxBlk->TxRate,
2369 NextMpduSize + EncryptionOverhead);
2373 pTxBlk->FrameGap = IFS_HTTXOP;
2375 pTxBlk->FrameGap = IFS_SIFS;
2377 RTMPWriteTxWI_Data(pAd,
2378 (struct rt_txwi *) (&pTxBlk->
2379 HeaderBuf[TXINFO_SIZE]),
2382 HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber);
2384 pAd->RalinkCounters.KickTxCount++;
2385 pAd->RalinkCounters.OneSecTxDoneCount++;
2387 /* Update the frame number, remaining size of the NDIS packet payload. */
2389 /* space for 802.11 header. */
2390 if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap)
2391 pTxBlk->MpduHeaderLen -= LENGTH_802_1_H;
2394 SrcRemainingBytes -= pTxBlk->SrcBufLen;
2395 pTxBlk->pSrcBufData += pTxBlk->SrcBufLen;
2397 pHeader_802_11->Frag++; /* increase Frag # */
2399 } while (SrcRemainingBytes > 0);
2404 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2405 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2408 #define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \
2409 while(_pTxBlk->TxPacketList.Head) \
2411 _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList); \
2412 RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \
2416 ========================================================================
2418 Routine Description:
2419 Copy frame from waiting queue into relative ring buffer and set
2420 appropriate ASIC register to kick hardware encryption before really
2424 pAd Pointer to our adapter
2425 void * Pointer to outgoing Ndis frame
2426 NumberOfFrag Number of fragment required
2431 IRQL = DISPATCH_LEVEL
2435 ========================================================================
2437 int STAHardTransmit(struct rt_rtmp_adapter *pAd,
2438 struct rt_tx_blk *pTxBlk, u8 QueIdx)
2441 struct rt_queue_entry *pQEntry;
2443 /* --------------------------------------------- */
2444 /* STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION. */
2445 /* --------------------------------------------- */
2447 ASSERT(pTxBlk->TxPacketList.Number);
2448 if (pTxBlk->TxPacketList.Head == NULL) {
2449 DBGPRINT(RT_DEBUG_ERROR,
2450 ("pTxBlk->TotalFrameNum == %ld!\n",
2451 pTxBlk->TxPacketList.Number));
2452 return NDIS_STATUS_FAILURE;
2455 pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head);
2457 /* ------------------------------------------------------------------ */
2458 /* STEP 1. WAKE UP PHY */
2459 /* outgoing frame always wakeup PHY to prevent frame lost and */
2460 /* turn off PSM bit to improve performance */
2461 /* ------------------------------------------------------------------ */
2462 /* not to change PSM bit, just send this frame out? */
2463 if ((pAd->StaCfg.Psm == PWR_SAVE)
2464 && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) {
2465 DBGPRINT_RAW(RT_DEBUG_INFO, ("AsicForceWakeup At HardTx\n"));
2467 AsicForceWakeup(pAd, TRUE);
2468 #endif /* RTMP_MAC_PCI // */
2470 RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_FORCE_WAKE_UP, NULL, 0);
2471 #endif /* RTMP_MAC_USB // */
2473 /* It should not change PSM bit, when APSD turn on. */
2475 (pAd->CommonCfg.bAPSDCapable
2476 && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
2477 && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE))
2478 || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
2479 || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket))) {
2480 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
2481 (pAd->StaCfg.WindowsPowerMode ==
2482 Ndis802_11PowerModeFast_PSP))
2483 RTMP_SET_PSM_BIT(pAd, PWR_ACTIVE);
2486 switch (pTxBlk->TxFrameType) {
2487 case TX_AMPDU_FRAME:
2488 STA_AMPDU_Frame_Tx(pAd, pTxBlk);
2490 case TX_AMSDU_FRAME:
2491 STA_AMSDU_Frame_Tx(pAd, pTxBlk);
2493 case TX_LEGACY_FRAME:
2494 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2496 case TX_MCAST_FRAME:
2497 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2499 case TX_RALINK_FRAME:
2500 STA_ARalink_Frame_Tx(pAd, pTxBlk);
2503 STA_Fragment_Frame_Tx(pAd, pTxBlk);
2507 /* It should not happened! */
2508 DBGPRINT(RT_DEBUG_ERROR,
2509 ("Send a packet was not classified! It should not happen!\n"));
2510 while (pTxBlk->TxPacketList.Number) {
2512 RemoveHeadQueue(&pTxBlk->TxPacketList);
2513 pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2515 RELEASE_NDIS_PACKET(pAd, pPacket,
2516 NDIS_STATUS_FAILURE);
2522 return (NDIS_STATUS_SUCCESS);
2526 unsigned long HashBytesPolynomial(u8 * value, unsigned int len)
2528 unsigned char *word = value;
2529 unsigned int ret = 0;
2532 for (i = 0; i < len; i++) {
2534 ret ^= (unsigned int)(word[i]) << mod;
2535 ret ^= (unsigned int)(word[i]) >> (32 - mod);
2540 void Sta_Announce_or_Forward_802_3_Packet(struct rt_rtmp_adapter *pAd,
2545 announce_802_3_packet(pAd, pPacket);
2547 /* release packet */
2548 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);