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 *************************************************************************
28 #include "../rt_config.h"
30 #define MAX_TX_IN_TBTT (16)
33 UCHAR SNAP_802_1H[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
34 UCHAR SNAP_BRIDGE_TUNNEL[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8};
35 // Add Cisco Aironet SNAP heade for CCX2 support
36 UCHAR SNAP_AIRONET[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00};
37 UCHAR CKIP_LLC_SNAP[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02};
38 UCHAR EAPOL_LLC_SNAP[]= {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e};
39 UCHAR EAPOL[] = {0x88, 0x8e};
40 UCHAR TPID[] = {0x81, 0x00}; /* VLAN related */
42 UCHAR IPX[] = {0x81, 0x37};
43 UCHAR APPLE_TALK[] = {0x80, 0xf3};
44 UCHAR RateIdToPlcpSignal[12] = {
45 0, /* RATE_1 */ 1, /* RATE_2 */ 2, /* RATE_5_5 */ 3, /* RATE_11 */ // see BBP spec
46 11, /* RATE_6 */ 15, /* RATE_9 */ 10, /* RATE_12 */ 14, /* RATE_18 */ // see IEEE802.11a-1999 p.14
47 9, /* RATE_24 */ 13, /* RATE_36 */ 8, /* RATE_48 */ 12 /* RATE_54 */ }; // see IEEE802.11a-1999 p.14
49 UCHAR OfdmSignalToRateId[16] = {
50 RATE_54, RATE_54, RATE_54, RATE_54, // OFDM PLCP Signal = 0, 1, 2, 3 respectively
51 RATE_54, RATE_54, RATE_54, RATE_54, // OFDM PLCP Signal = 4, 5, 6, 7 respectively
52 RATE_48, RATE_24, RATE_12, RATE_6, // OFDM PLCP Signal = 8, 9, 10, 11 respectively
53 RATE_54, RATE_36, RATE_18, RATE_9, // OFDM PLCP Signal = 12, 13, 14, 15 respectively
56 UCHAR OfdmRateToRxwiMCS[12] = {
58 0, 1, 2, 3, // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3
59 4, 5, 6, 7, // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7
61 UCHAR RxwiMCSToOfdmRate[12] = {
62 RATE_6, RATE_9, RATE_12, RATE_18,
63 RATE_24, RATE_36, RATE_48, RATE_54, // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3
64 4, 5, 6, 7, // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7
67 char* MCSToMbps[] = {"1Mbps","2Mbps","5.5Mbps","11Mbps","06Mbps","09Mbps","12Mbps","18Mbps","24Mbps","36Mbps","48Mbps","54Mbps","MM-0","MM-1","MM-2","MM-3","MM-4","MM-5","MM-6","MM-7","MM-8","MM-9","MM-10","MM-11","MM-12","MM-13","MM-14","MM-15","MM-32","ee1","ee2","ee3"};
69 UCHAR default_cwmin[]={CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1, CW_MIN_IN_BITS-2};
70 //UCHAR default_cwmax[]={CW_MAX_IN_BITS, CW_MAX_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1};
71 UCHAR default_sta_aifsn[]={3,7,2,2};
73 UCHAR MapUserPriorityToAccessCategory[8] = {QID_AC_BE, QID_AC_BK, QID_AC_BK, QID_AC_BE, QID_AC_VI, QID_AC_VI, QID_AC_VO, QID_AC_VO};
77 ========================================================================
80 API for MLME to transmit management frame to AP (BSS Mode)
81 or station (IBSS Mode)
84 pAd Pointer to our adapter
85 pData Pointer to the outgoing 802.11 frame
86 Length Size of outgoing management frame
98 ========================================================================
100 NDIS_STATUS MiniportMMRequest(
101 IN PRTMP_ADAPTER pAd,
106 PNDIS_PACKET pPacket;
107 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
110 UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN];
112 ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
118 IrqState = pAd->irq_disabled;
122 // Reset is in progress, stop immediately
123 if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
124 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)||
125 !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
127 Status = NDIS_STATUS_FAILURE;
131 // Check Free priority queue
132 // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing.
135 if (pAd->MACVersion == 0x28600100)
137 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
141 FreeNum = GET_MGMTRING_FREENO(pAd);
146 // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870
147 NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE));
148 Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE), pData, Length);
149 if (Status != NDIS_STATUS_SUCCESS)
151 DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
155 //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
156 //pAd->CommonCfg.MlmeRate = RATE_2;
159 Status = MlmeHardTransmit(pAd, QueIdx, pPacket);
160 if (Status != NDIS_STATUS_SUCCESS)
161 RTMPFreeNdisPacket(pAd, pPacket);
165 pAd->RalinkCounters.MgmtRingFullCount++;
166 DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n",
167 QueIdx, pAd->RalinkCounters.MgmtRingFullCount));
178 NDIS_STATUS MlmeDataHardTransmit(
179 IN PRTMP_ADAPTER pAd,
181 IN PNDIS_PACKET pPacket);
183 #define MAX_DATAMM_RETRY 3
185 ========================================================================
188 API for MLME to transmit management frame to AP (BSS Mode)
189 or station (IBSS Mode)
192 pAd Pointer to our adapter
193 pData Pointer to the outgoing 802.11 frame
194 Length Size of outgoing management frame
202 IRQL = DISPATCH_LEVEL
206 ========================================================================
208 NDIS_STATUS MiniportDataMMRequest(
209 IN PRTMP_ADAPTER pAd,
214 PNDIS_PACKET pPacket;
215 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
219 UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN];
221 ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
224 IrqState = pAd->irq_disabled;
228 // Reset is in progress, stop immediately
229 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
230 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)||
231 !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
233 Status = NDIS_STATUS_FAILURE;
237 // Check Free priority queue
238 // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing.
242 // free Tx(QueIdx) resources
243 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
247 // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870
248 NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE));
249 Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE), pData, Length);
250 if (Status != NDIS_STATUS_SUCCESS)
252 DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
256 //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
257 //pAd->CommonCfg.MlmeRate = RATE_2;
260 Status = MlmeDataHardTransmit(pAd, QueIdx, pPacket);
261 if (Status != NDIS_STATUS_SUCCESS)
262 RTMPFreeNdisPacket(pAd, pPacket);
263 retry = MAX_DATAMM_RETRY;
269 printk("retry %d\n", retry);
270 pAd->RalinkCounters.MgmtRingFullCount++;
272 if (retry >= MAX_DATAMM_RETRY)
274 DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in DataRing, MgmtRingFullCount=%ld!\n",
275 QueIdx, pAd->RalinkCounters.MgmtRingFullCount));
279 } while (retry < MAX_DATAMM_RETRY);
291 ========================================================================
294 Copy frame from waiting queue into relative ring buffer and set
295 appropriate ASIC register to kick hardware transmit function
298 pAd Pointer to our adapter
299 pBuffer Pointer to memory of outgoing frame
300 Length Size of outgoing management frame
308 IRQL = DISPATCH_LEVEL
312 ========================================================================
314 NDIS_STATUS MlmeHardTransmit(
315 IN PRTMP_ADAPTER pAd,
317 IN PNDIS_PACKET pPacket)
319 if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
322 return NDIS_STATUS_FAILURE;
325 return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
329 NDIS_STATUS MlmeDataHardTransmit(
330 IN PRTMP_ADAPTER pAd,
332 IN PNDIS_PACKET pPacket)
334 if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
337 return NDIS_STATUS_FAILURE;
341 return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
349 NDIS_STATUS MlmeHardTransmitMgmtRing(
350 IN PRTMP_ADAPTER pAd,
352 IN PNDIS_PACKET pPacket)
354 PACKET_INFO PacketInfo;
357 PHEADER_802_11 pHeader_802_11;
358 BOOLEAN bAckRequired, bInsertTimestamp;
360 PTXWI_STRUC pFirstTxWI;
361 MAC_TABLE_ENTRY *pMacEntry = NULL;
363 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
365 // Make sure MGMT ring resource won't be used by other threads
366 // sample, for IRQ LOCK -> SEM LOCK
367 // IrqState = pAd->irq_disabled;
369 RTMP_SEM_LOCK(&pAd->MgmtRingLock);
372 if (pSrcBufVA == NULL)
374 // The buffer shouldn't be NULL
376 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
377 return NDIS_STATUS_FAILURE;
380 #ifdef CONFIG_STA_SUPPORT
381 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
383 // outgoing frame always wakeup PHY to prevent frame lost
384 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
385 AsicForceWakeup(pAd, TRUE);
387 #endif // CONFIG_STA_SUPPORT //
389 pFirstTxWI = (PTXWI_STRUC)(pSrcBufVA + TXINFO_SIZE);
390 pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); //TXWI_SIZE);
392 if (pHeader_802_11->Addr1[0] & 0x01)
394 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
398 MlmeRate = pAd->CommonCfg.MlmeRate;
401 // Verify Mlme rate for a / g bands.
402 if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
405 if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
406 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
408 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
411 #ifdef CONFIG_STA_SUPPORT
412 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
414 // Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode.
415 if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED
416 #ifdef DOT11_N_SUPPORT
417 || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED
418 #endif // DOT11_N_SUPPORT //
421 if (pAd->LatchRfRegs.Channel > 14)
422 pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
424 pAd->CommonCfg.MlmeTransmit.field.MODE = 0;
427 #endif // CONFIG_STA_SUPPORT //
430 // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
431 // Snice it's been set to 0 while on MgtMacHeaderInit
432 // By the way this will cause frame to be send on PWR_SAVE failed.
434 // pHeader_802_11->FC.PwrMgmt = 0; // (pAd->StaCfg.Psm == PWR_SAVE);
436 // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
437 #ifdef CONFIG_STA_SUPPORT
438 // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
439 if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL))
441 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
442 (pHeader_802_11->FC.SubType == SUBTYPE_ACTION))
443 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
445 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
447 #endif // CONFIG_STA_SUPPORT //
449 bInsertTimestamp = FALSE;
450 if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
452 #ifdef CONFIG_STA_SUPPORT
453 //Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue.
454 if ((pAd->OpMode == OPMODE_STA) && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL))
456 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
458 #endif // CONFIG_STA_SUPPORT //
459 bAckRequired = FALSE;
461 else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
464 //pHeader_802_11->Sequence = pAd->Sequence;
466 if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
468 bAckRequired = FALSE;
469 pHeader_802_11->Duration = 0;
474 pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
475 if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
477 bInsertTimestamp = TRUE;
482 pHeader_802_11->Sequence = pAd->Sequence++;
483 if (pAd->Sequence >0xfff)
486 // Before radar detection done, mgmt frame can not be sent but probe req
487 // Because we need to use probe req to trigger driver to send probe req in passive scan
488 if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
489 && (pAd->CommonCfg.bIEEE80211H == 1)
490 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
492 DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
494 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
495 return (NDIS_STATUS_FAILURE);
499 RTMPFrameEndianChange(pAd, (PUCHAR)pHeader_802_11, DIR_WRITE, FALSE);
503 // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
504 // should always has only one ohysical buffer, and the whole frame size equals
505 // to the first scatter buffer size
508 // Initialize TX Descriptor
509 // For inter-frame gap, the number is for this frame and next frame
510 // For MLME rate, we will fix as 2Mb to match other vendor's implement
511 // pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
513 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
514 if (pMacEntry == NULL)
516 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
517 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
521 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
522 bInsertTimestamp, FALSE, bAckRequired, FALSE,
523 0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE),
524 pMacEntry->MaxHTPhyMode.field.MCS, 0,
525 (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
526 IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
530 RTMPWIEndianChange((PUCHAR)pFirstTxWI, TYPE_TXWI);
533 // Now do hardware-depened kick out.
534 HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen);
536 // Make sure to release MGMT ring resource
538 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
539 return NDIS_STATUS_SUCCESS;
543 /********************************************************************************
545 New DeQueue Procedures.
547 ********************************************************************************/
549 #define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \
551 if (bIntContext == FALSE) \
552 RTMP_IRQ_LOCK((lock), IrqFlags); \
555 #define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \
557 if (bIntContext == FALSE) \
558 RTMP_IRQ_UNLOCK((lock), IrqFlags); \
563 ========================================================================
564 Tx Path design algorithm:
565 Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal),
566 Specific Packet Type. Following show the classification rule and policy for each kinds of packets.
567 Classification Rule=>
568 Multicast: (*addr1 & 0x01) == 0x01
569 Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc.
570 11N Rate : If peer support HT
571 (1).AMPDU -- If TXBA is negotiated.
572 (2).AMSDU -- If AMSDU is capable for both peer and ourself.
573 *). AMSDU can embedded in a AMPDU, but now we didn't support it.
574 (3).Normal -- Other packets which send as 11n rate.
576 B/G Rate : If peer is b/g only.
577 (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6
578 (2).Normal -- Other packets which send as b/g rate.
580 The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
582 Classified Packet Handle Rule=>
584 No ACK, //pTxBlk->bAckRequired = FALSE;
585 No WMM, //pTxBlk->bWMM = FALSE;
586 No piggyback, //pTxBlk->bPiggyBack = FALSE;
587 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
588 Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use
589 the same policy to handle it.
590 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
593 No piggyback, //pTxBlk->bPiggyBack = FALSE;
605 ========================================================================
607 static UCHAR TxPktClassification(
608 IN RTMP_ADAPTER *pAd,
609 IN PNDIS_PACKET pPacket)
611 UCHAR TxFrameType = TX_UNKOWN_FRAME;
613 MAC_TABLE_ENTRY *pMacEntry = NULL;
614 #ifdef DOT11_N_SUPPORT
615 BOOLEAN bHTRate = FALSE;
616 #endif // DOT11_N_SUPPORT //
618 Wcid = RTMP_GET_PACKET_WCID(pPacket);
619 if (Wcid == MCAST_WCID)
620 { // Handle for RA is Broadcast/Multicast Address.
621 return TX_MCAST_FRAME;
624 // Handle for unicast packets
625 pMacEntry = &pAd->MacTab.Content[Wcid];
626 if (RTMP_GET_PACKET_LOWRATE(pPacket))
627 { // It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame
628 TxFrameType = TX_LEGACY_FRAME;
630 #ifdef DOT11_N_SUPPORT
631 else if (IS_HT_RATE(pMacEntry))
632 { // it's a 11n capable packet
634 // Depends on HTPhyMode to check if the peer support the HTRate transmission.
635 // Currently didn't support A-MSDU embedded in A-MPDU
637 if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE))
638 TxFrameType = TX_LEGACY_FRAME;
639 #ifdef UAPSD_AP_SUPPORT
640 else if (RTMP_GET_PACKET_EOSP(pPacket))
641 TxFrameType = TX_LEGACY_FRAME;
642 #endif // UAPSD_AP_SUPPORT //
643 else if((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0)
644 return TX_AMPDU_FRAME;
645 else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED))
646 return TX_AMSDU_FRAME;
648 TxFrameType = TX_LEGACY_FRAME;
650 #endif // DOT11_N_SUPPORT //
652 { // it's a legacy b/g packet.
653 if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) &&
654 (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) &&
655 (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
656 { // if peer support Ralink Aggregation, we use it.
657 TxFrameType = TX_RALINK_FRAME;
661 TxFrameType = TX_LEGACY_FRAME;
665 // Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU.
666 if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) && (TxFrameType == TX_LEGACY_FRAME))
667 TxFrameType = TX_FRAG_FRAME;
673 BOOLEAN RTMP_FillTxBlkInfo(
674 IN RTMP_ADAPTER *pAd,
677 PACKET_INFO PacketInfo;
678 PNDIS_PACKET pPacket;
679 PMAC_TABLE_ENTRY pMacEntry = NULL;
681 pPacket = pTxBlk->pPacket;
682 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
684 pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket);
685 pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket);
686 pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket);
687 pTxBlk->FrameGap = IFS_HTTXOP; // ASIC determine Frame Gap
689 if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket))
690 TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame);
692 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame);
694 // Default to clear this flag
695 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS);
698 if (pTxBlk->Wcid == MCAST_WCID)
700 pTxBlk->pMacEntry = NULL;
702 #ifdef MCAST_RATE_SPECIFIC
703 PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket);
704 if (((*pDA & 0x01) == 0x01) && (*pDA != 0xff))
705 pTxBlk->pTransmit = &pAd->CommonCfg.MCastPhyMode;
707 #endif // MCAST_RATE_SPECIFIC //
708 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
711 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); // AckRequired = FALSE, when broadcast packet in Adhoc mode.
712 //TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate);
713 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag);
714 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
715 if (RTMP_GET_PACKET_MOREDATA(pPacket))
717 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
723 pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
724 pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode;
726 pMacEntry = pTxBlk->pMacEntry;
729 // For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK.
730 if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK)
731 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
733 TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired);
737 #ifdef CONFIG_STA_SUPPORT
738 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
741 // If support WMM, enable it.
742 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
743 CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))
744 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM);
746 // if (pAd->StaCfg.bAutoTxRateSwitch)
747 // TX_BLK_SET_FLAG(pTxBlk, fTX_AutoRateSwitch);
749 #endif // CONFIG_STA_SUPPORT //
752 if (pTxBlk->TxFrameType == TX_LEGACY_FRAME)
754 if ( (RTMP_GET_PACKET_LOWRATE(pPacket)) ||
755 ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1)))
756 { // Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate.
757 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
758 #ifdef DOT11_N_SUPPORT
759 // Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it???
760 if (IS_HT_STA(pTxBlk->pMacEntry) &&
761 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) &&
762 ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)))
764 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
765 TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS);
767 #endif // DOT11_N_SUPPORT //
770 #ifdef DOT11_N_SUPPORT
771 if ( (IS_HT_RATE(pMacEntry) == FALSE) &&
772 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE)))
773 { // Currently piggy-back only support when peer is operate in b/g mode.
774 TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack);
776 #endif // DOT11_N_SUPPORT //
778 if (RTMP_GET_PACKET_MOREDATA(pPacket))
780 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
782 #ifdef UAPSD_AP_SUPPORT
783 if (RTMP_GET_PACKET_EOSP(pPacket))
785 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP);
787 #endif // UAPSD_AP_SUPPORT //
789 else if (pTxBlk->TxFrameType == TX_FRAG_FRAME)
791 TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag);
794 pMacEntry->DebugTxCount++;
804 BOOLEAN CanDoAggregateTransmit(
805 IN RTMP_ADAPTER *pAd,
806 IN NDIS_PACKET *pPacket,
810 //printk("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType);
812 if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
815 if (RTMP_GET_PACKET_DHCP(pPacket) ||
816 RTMP_GET_PACKET_EAPOL(pPacket) ||
817 RTMP_GET_PACKET_WAI(pPacket))
820 if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) &&
821 ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100)))
822 { // For AMSDU, allow the packets with total length < max-amsdu size
826 if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) &&
827 (pTxBlk->TxPacketList.Number == 2))
828 { // For RALINK-Aggregation, allow two frames in one batch.
832 #ifdef CONFIG_STA_SUPPORT
833 if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP
836 #endif // CONFIG_STA_SUPPORT //
843 ========================================================================
846 To do the enqueue operation and extract the first item of waiting
847 list. If a number of available shared memory segments could meet
848 the request of extracted item, the extracted item will be fragmented
849 into shared memory segments.
852 pAd Pointer to our adapter
853 pQueue Pointer to Waiting Queue
858 IRQL = DISPATCH_LEVEL
862 ========================================================================
864 VOID RTMPDeQueuePacket(
865 IN PRTMP_ADAPTER pAd,
866 IN BOOLEAN bIntContext,
867 IN UCHAR QIdx, /* BulkOutPipeId */
868 IN UCHAR Max_Tx_Packets)
870 PQUEUE_ENTRY pEntry = NULL;
871 PNDIS_PACKET pPacket;
872 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
874 PQUEUE_HEADER pQueue;
875 ULONG FreeNumber[NUM_OF_TX_RING];
876 UCHAR QueIdx, sQIdx, eQIdx;
877 unsigned long IrqFlags = 0;
878 BOOLEAN hasTxDesc = FALSE;
884 RtmpDiagStruct *pDiagStruct = &pAd->DiagStruct;
888 if (QIdx == NUM_OF_TX_RING)
891 //PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA)
892 #ifdef CONFIG_STA_SUPPORT
893 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
894 eQIdx = 3; // 4 ACs, start from 0.
895 #endif // CONFIG_STA_SUPPORT //
899 sQIdx = eQIdx = QIdx;
902 for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++)
906 RT28XX_START_DEQUEUE(pAd, QueIdx, IrqFlags);
909 firstRound = ((QueIdx == 0) ? TRUE : FALSE);
910 #endif // DBG_DIAGNOSE //
914 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |
915 fRTMP_ADAPTER_RADIO_OFF |
916 fRTMP_ADAPTER_RESET_IN_PROGRESS |
917 fRTMP_ADAPTER_HALT_IN_PROGRESS |
918 fRTMP_ADAPTER_NIC_NOT_EXIST))))
920 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
924 if (Count >= Max_Tx_Packets)
927 DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
928 if (&pAd->TxSwQueue[QueIdx] == NULL)
931 if (firstRound == TRUE)
932 pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][0]++;
933 #endif // DBG_DIAGNOSE //
934 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
939 // probe the Queue Head
940 pQueue = &pAd->TxSwQueue[QueIdx];
941 if ((pEntry = pQueue->Head) == NULL)
943 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
948 NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK));
949 //InitializeQueueHeader(&pTxBlk->TxPacketList); // Didn't need it because we already memzero it.
950 pTxBlk->QueIdx = QueIdx;
952 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
954 // Early check to make sure we have enoguh Tx Resource.
955 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
958 pAd->PrivateInfo.TxRingFullCnt++;
960 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
965 pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
966 pEntry = RemoveHeadQueue(pQueue);
967 pTxBlk->TotalFrameNum++;
968 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
969 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
970 pTxBlk->pPacket = pPacket;
971 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
973 if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME)
975 // Enhance SW Aggregation Mechanism
976 if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType))
978 InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
979 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
984 if((pEntry = pQueue->Head) == NULL)
987 // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation.
988 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
989 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
990 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
991 if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE))
994 //Remove the packet from the TxSwQueue and insert into pTxBlk
995 pEntry = RemoveHeadQueue(pQueue);
997 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
998 pTxBlk->TotalFrameNum++;
999 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
1000 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
1001 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
1004 if (pTxBlk->TxPacketList.Number == 1)
1005 pTxBlk->TxFrameType = TX_LEGACY_FRAME;
1009 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1012 Count += pTxBlk->TxPacketList.Number;
1014 // Do HardTransmit now.
1015 #ifdef CONFIG_STA_SUPPORT
1016 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1017 Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
1018 #endif // CONFIG_STA_SUPPORT //
1021 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
1025 RTUSBKickBulkOut(pAd);
1033 ========================================================================
1035 Routine Description:
1036 Calculates the duration which is required to transmit out frames
1037 with given size and specified rate.
1040 pAd Pointer to our adapter
1042 Size Frame size in units of byte
1045 Duration number in units of usec
1047 IRQL = PASSIVE_LEVEL
1048 IRQL = DISPATCH_LEVEL
1052 ========================================================================
1054 USHORT RTMPCalcDuration(
1055 IN PRTMP_ADAPTER pAd,
1061 if (Rate < RATE_FIRST_OFDM_RATE) // CCK
1063 if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED))
1064 Duration = 96; // 72+24 preamble+plcp
1066 Duration = 192; // 144+48 preamble+plcp
1068 Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]);
1069 if ((Size << 4) % RateIdTo500Kbps[Rate])
1072 else if (Rate <= RATE_LAST_OFDM_RATE)// OFDM rates
1074 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
1075 Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
1076 if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
1081 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
1084 return (USHORT)Duration;
1089 ========================================================================
1091 Routine Description:
1092 Calculates the duration which is required to transmit out frames
1093 with given size and specified rate.
1096 pTxWI Pointer to head of each MPDU to HW.
1097 Ack Setting for Ack requirement bit
1098 Fragment Setting for Fragment bit
1099 RetryMode Setting for retry mode
1100 Ifs Setting for IFS gap
1101 Rate Setting for transmit rate
1102 Service Setting for service
1104 TxPreamble Short or Long preamble when using CCK rates
1105 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1110 IRQL = PASSIVE_LEVEL
1111 IRQL = DISPATCH_LEVEL
1113 See also : BASmartHardTransmit() !!!
1115 ========================================================================
1118 IN PRTMP_ADAPTER pAd,
1119 IN PTXWI_STRUC pOutTxWI,
1122 IN BOOLEAN InsTimestamp,
1125 IN BOOLEAN NSeq, // HW new a sequence.
1134 IN HTTRANSMIT_SETTING *pTransmit)
1136 PMAC_TABLE_ENTRY pMac = NULL;
1140 if (WCID < MAX_LEN_OF_MAC_TABLE)
1141 pMac = &pAd->MacTab.Content[WCID];
1144 // Always use Long preamble before verifiation short preamble functionality works well.
1145 // Todo: remove the following line if short preamble functionality works
1147 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1148 NdisZeroMemory(&TxWI, TXWI_SIZE);
1153 pTxWI->CFACK = CFACK;
1154 pTxWI->TS= InsTimestamp;
1155 pTxWI->AMPDU = AMPDU;
1157 pTxWI->txop= Txopmode;
1160 // John tune the performace with Intel Client in 20 MHz performance
1161 #ifdef DOT11_N_SUPPORT
1162 BASize = pAd->CommonCfg.TxBASize;
1166 pTxWI->BAWinSize = BASize;
1167 pTxWI->ShortGI = pTransmit->field.ShortGI;
1168 pTxWI->STBC = pTransmit->field.STBC;
1169 #endif // DOT11_N_SUPPORT //
1171 pTxWI->WirelessCliID = WCID;
1172 pTxWI->MPDUtotalByteCount = Length;
1173 pTxWI->PacketId = PID;
1175 // If CCK or OFDM, BW must be 20
1176 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1178 pTxWI->MCS = pTransmit->field.MCS;
1179 pTxWI->PHYMODE = pTransmit->field.MODE;
1180 pTxWI->CFACK = CfAck;
1182 #ifdef DOT11_N_SUPPORT
1185 if (pAd->CommonCfg.bMIMOPSEnable)
1187 if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1189 // Dynamic MIMO Power Save Mode
1192 else if (pMac->MmpsMode == MMPS_STATIC)
1194 // Static MIMO Power Save Mode
1195 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1202 //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;
1203 if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled))
1205 pTxWI->MpduDensity = 7;
1209 pTxWI->MpduDensity = pMac->MpduDensity;
1212 #endif // DOT11_N_SUPPORT //
1214 pTxWI->PacketId = pTxWI->MCS;
1215 NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC));
1219 VOID RTMPWriteTxWI_Data(
1220 IN PRTMP_ADAPTER pAd,
1221 IN OUT PTXWI_STRUC pTxWI,
1224 HTTRANSMIT_SETTING *pTransmit;
1225 PMAC_TABLE_ENTRY pMacEntry;
1226 #ifdef DOT11_N_SUPPORT
1228 #endif // DOT11_N_SUPPORT //
1233 pTransmit = pTxBlk->pTransmit;
1234 pMacEntry = pTxBlk->pMacEntry;
1238 // Always use Long preamble before verifiation short preamble functionality works well.
1239 // Todo: remove the following line if short preamble functionality works
1241 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1242 NdisZeroMemory(pTxWI, TXWI_SIZE);
1244 pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1245 pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1246 pTxWI->txop = pTxBlk->FrameGap;
1248 pTxWI->WirelessCliID = pTxBlk->Wcid;
1250 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1251 pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
1253 // If CCK or OFDM, BW must be 20
1254 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1255 #ifdef DOT11_N_SUPPORT
1256 pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
1258 // John tune the performace with Intel Client in 20 MHz performance
1259 BASize = pAd->CommonCfg.TxBASize;
1260 if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry))
1262 UCHAR RABAOriIdx = 0; //The RA's BA Originator table index.
1264 RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
1265 BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1268 pTxWI->TxBF = pTransmit->field.TxBF;
1269 pTxWI->BAWinSize = BASize;
1270 pTxWI->ShortGI = pTransmit->field.ShortGI;
1271 pTxWI->STBC = pTransmit->field.STBC;
1272 #endif // DOT11_N_SUPPORT //
1274 pTxWI->MCS = pTransmit->field.MCS;
1275 pTxWI->PHYMODE = pTransmit->field.MODE;
1277 #ifdef DOT11_N_SUPPORT
1280 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1282 // Dynamic MIMO Power Save Mode
1285 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1287 // Static MIMO Power Save Mode
1288 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1295 if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled))
1297 pTxWI->MpduDensity = 7;
1301 pTxWI->MpduDensity = pMacEntry->MpduDensity;
1304 #endif // DOT11_N_SUPPORT //
1307 if (pTxBlk->QueIdx== 0)
1309 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1310 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1312 #endif // DBG_DIAGNOSE //
1314 // for rate adapation
1315 pTxWI->PacketId = pTxWI->MCS;
1316 #ifdef INF_AMAZON_SE
1317 /*Iverson patch for WMM A5-T07 ,WirelessStaToWirelessSta do not bulk out aggregate */
1318 if( RTMP_GET_PACKET_NOBULKOUT(pTxBlk->pPacket))
1320 if(pTxWI->PHYMODE == MODE_CCK)
1322 pTxWI->PacketId = 6;
1325 #endif // INF_AMAZON_SE //
1329 VOID RTMPWriteTxWI_Cache(
1330 IN PRTMP_ADAPTER pAd,
1331 IN OUT PTXWI_STRUC pTxWI,
1334 PHTTRANSMIT_SETTING /*pTxHTPhyMode,*/ pTransmit;
1335 PMAC_TABLE_ENTRY pMacEntry;
1340 pMacEntry = pTxBlk->pMacEntry;
1341 pTransmit = pTxBlk->pTransmit;
1343 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
1344 //if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pMacEntry))
1345 //if (TX_BLK_TEST_FLAG(pTxBlk, fTX_AutoRateSwitch))
1346 if (pMacEntry->bAutoTxRateSwitch)
1348 pTxWI->txop = IFS_HTTXOP;
1350 // If CCK or OFDM, BW must be 20
1351 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1352 pTxWI->ShortGI = pTransmit->field.ShortGI;
1353 pTxWI->STBC = pTransmit->field.STBC;
1355 pTxWI->MCS = pTransmit->field.MCS;
1356 pTxWI->PHYMODE = pTransmit->field.MODE;
1358 // set PID for TxRateSwitching
1359 pTxWI->PacketId = pTransmit->field.MCS;
1362 #ifdef DOT11_N_SUPPORT
1363 pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE);
1366 if (pAd->CommonCfg.bMIMOPSEnable)
1368 // MIMO Power Save Mode
1369 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1371 // Dynamic MIMO Power Save Mode
1374 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1376 // Static MIMO Power Save Mode
1377 if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7))
1384 #endif // DOT11_N_SUPPORT //
1387 if (pTxBlk->QueIdx== 0)
1389 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1390 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1392 #endif // DBG_DIAGNOSE //
1394 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1400 ========================================================================
1402 Routine Description:
1403 Calculates the duration which is required to transmit out frames
1404 with given size and specified rate.
1407 pTxD Pointer to transmit descriptor
1408 Ack Setting for Ack requirement bit
1409 Fragment Setting for Fragment bit
1410 RetryMode Setting for retry mode
1411 Ifs Setting for IFS gap
1412 Rate Setting for transmit rate
1413 Service Setting for service
1415 TxPreamble Short or Long preamble when using CCK rates
1416 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1421 IRQL = PASSIVE_LEVEL
1422 IRQL = DISPATCH_LEVEL
1424 ========================================================================
1426 VOID RTMPWriteTxDescriptor(
1427 IN PRTMP_ADAPTER pAd,
1433 // Always use Long preamble before verifiation short preamble functionality works well.
1434 // Todo: remove the following line if short preamble functionality works
1436 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1438 pTxD->WIV = (bWIV) ? 1: 0;
1439 pTxD->QSEL= (QueueSEL);
1440 if (pAd->bGenOneHCCA == TRUE)
1441 pTxD->QSEL= FIFO_HCCA;
1446 // should be called only when -
1447 // 1. MEADIA_CONNECTED
1448 // 2. AGGREGATION_IN_USED
1449 // 3. Fragmentation not in used
1450 // 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible
1451 BOOLEAN TxFrameIsAggregatible(
1452 IN PRTMP_ADAPTER pAd,
1453 IN PUCHAR pPrevAddr1,
1457 // can't aggregate EAPOL (802.1x) frame
1458 if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1461 // can't aggregate multicast/broadcast frame
1462 if (p8023hdr[0] & 0x01)
1465 if (INFRA_ON(pAd)) // must be unicast to AP
1467 else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA
1475 ========================================================================
1477 Routine Description:
1478 Check the MSDU Aggregation policy
1479 1.HT aggregation is A-MSDU
1480 2.legaacy rate aggregation is software aggregation by Ralink.
1488 ========================================================================
1490 BOOLEAN PeerIsAggreOn(
1491 IN PRTMP_ADAPTER pAd,
1493 IN PMAC_TABLE_ENTRY pMacEntry)
1495 ULONG AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
1497 if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags))
1499 #ifdef DOT11_N_SUPPORT
1500 if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX)
1504 #endif // DOT11_N_SUPPORT //
1506 #ifdef AGGREGATION_SUPPORT
1507 if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
1508 { // legacy Ralink Aggregation support
1511 #endif // AGGREGATION_SUPPORT //
1520 ========================================================================
1522 Routine Description:
1523 Check and fine the packet waiting in SW queue with highest priority
1526 pAd Pointer to our adapter
1529 pQueue Pointer to Waiting Queue
1531 IRQL = DISPATCH_LEVEL
1535 ========================================================================
1537 PQUEUE_HEADER RTMPCheckTxSwQueue(
1538 IN PRTMP_ADAPTER pAd,
1543 // 2004-11-15 to be removed. test aggregation only
1544 // if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2))
1547 Number = pAd->TxSwQueue[QID_AC_BK].Number
1548 + pAd->TxSwQueue[QID_AC_BE].Number
1549 + pAd->TxSwQueue[QID_AC_VI].Number
1550 + pAd->TxSwQueue[QID_AC_VO].Number
1551 + pAd->TxSwQueue[QID_HCCA].Number;
1553 if (pAd->TxSwQueue[QID_AC_VO].Head != NULL)
1555 *pQueIdx = QID_AC_VO;
1556 return (&pAd->TxSwQueue[QID_AC_VO]);
1558 else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL)
1560 *pQueIdx = QID_AC_VI;
1561 return (&pAd->TxSwQueue[QID_AC_VI]);
1563 else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL)
1565 *pQueIdx = QID_AC_BE;
1566 return (&pAd->TxSwQueue[QID_AC_BE]);
1568 else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL)
1570 *pQueIdx = QID_AC_BK;
1571 return (&pAd->TxSwQueue[QID_AC_BK]);
1573 else if (pAd->TxSwQueue[QID_HCCA].Head != NULL)
1575 *pQueIdx = QID_HCCA;
1576 return (&pAd->TxSwQueue[QID_HCCA]);
1579 // No packet pending in Tx Sw queue
1580 *pQueIdx = QID_AC_BK;
1588 ========================================================================
1590 Routine Description:
1591 Suspend MSDU transmission
1594 pAd Pointer to our adapter
1601 ========================================================================
1603 VOID RTMPSuspendMsduTransmission(
1604 IN PRTMP_ADAPTER pAd)
1606 DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n"));
1610 // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
1611 // use Lowbound as R66 value on ScanNextChannel(...)
1613 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue);
1615 // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)
1616 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd)));
1617 RTMPSetAGCInitValue(pAd, BW_20);
1619 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1620 //RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000); // abort all TX rings
1625 ========================================================================
1627 Routine Description:
1628 Resume MSDU transmission
1631 pAd Pointer to our adapter
1636 IRQL = DISPATCH_LEVEL
1640 ========================================================================
1642 VOID RTMPResumeMsduTransmission(
1643 IN PRTMP_ADAPTER pAd)
1647 DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
1650 // After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value
1651 // R66 should not be 0
1652 if (pAd->BbpTuning.R66CurrentValue == 0)
1654 pAd->BbpTuning.R66CurrentValue = 0x38;
1655 DBGPRINT_ERR(("RTMPResumeMsduTransmission, R66CurrentValue=0...\n"));
1657 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue);
1659 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1660 // sample, for IRQ LOCK to SEM LOCK
1661 // IrqState = pAd->irq_disabled;
1663 // RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1665 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1669 UINT deaggregate_AMSDU_announce(
1670 IN PRTMP_ADAPTER pAd,
1671 PNDIS_PACKET pPacket,
1676 USHORT SubFrameSize;
1677 PHEADER_802_3 pAMSDUsubheader;
1679 UCHAR Header802_3[14];
1681 PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP;
1682 PNDIS_PACKET pClonePacket;
1688 while (DataSize > LENGTH_802_3)
1693 //hex_dump("subheader", pData, 64);
1694 pAMSDUsubheader = (PHEADER_802_3)pData;
1695 //pData += LENGTH_802_3;
1696 PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8);
1697 SubFrameSize = PayloadSize + LENGTH_802_3;
1700 if ((DataSize < SubFrameSize) || (PayloadSize > 1518 ))
1705 //printk("%d subframe: Size = %d\n", nMSDU, PayloadSize);
1707 pPayload = pData + LENGTH_802_3;
1709 pSA = pData + MAC_ADDR_LEN;
1711 // convert to 802.3 header
1712 CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP);
1714 #ifdef CONFIG_STA_SUPPORT
1715 if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) )
1717 // avoid local heap overflow, use dyanamic allocation
1718 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
1719 memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize);
1720 Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize;
1721 WpaEAPOLKeyAction(pAd, Elem);
1724 #endif // CONFIG_STA_SUPPORT //
1726 #ifdef CONFIG_STA_SUPPORT
1727 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1729 if (pRemovedLLCSNAP)
1731 pPayload -= LENGTH_802_3;
1732 PayloadSize += LENGTH_802_3;
1733 NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3);
1736 #endif // CONFIG_STA_SUPPORT //
1738 pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
1741 #ifdef CONFIG_STA_SUPPORT
1742 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1743 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket));
1744 #endif // CONFIG_STA_SUPPORT //
1748 // A-MSDU has padding to multiple of 4 including subframe header.
1749 // align SubFrameSize up to multiple of 4
1750 SubFrameSize = (SubFrameSize+3)&(~0x3);
1753 if (SubFrameSize > 1528 || SubFrameSize < 32)
1758 if (DataSize > SubFrameSize)
1760 pData += SubFrameSize;
1761 DataSize -= SubFrameSize;
1770 // finally release original rx packet
1771 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1777 UINT BA_Reorder_AMSDU_Annnounce(
1778 IN PRTMP_ADAPTER pAd,
1779 IN PNDIS_PACKET pPacket)
1785 pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
1786 DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
1788 nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
1795 ==========================================================================
1797 Look up the MAC address in the MAC table. Return NULL if not found.
1799 pEntry - pointer to the MAC entry; NULL is not found
1800 ==========================================================================
1802 MAC_TABLE_ENTRY *MacTableLookup(
1803 IN PRTMP_ADAPTER pAd,
1807 MAC_TABLE_ENTRY *pEntry = NULL;
1809 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1810 pEntry = pAd->MacTab.Hash[HashIdx];
1812 while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh))
1814 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1819 pEntry = pEntry->pNext;
1825 MAC_TABLE_ENTRY *MacTableInsertEntry(
1826 IN PRTMP_ADAPTER pAd,
1829 IN BOOLEAN CleanAll)
1833 MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
1838 if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
1842 #ifdef CONFIG_STA_SUPPORT
1843 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1844 if (pAd->StaCfg.BssType == BSS_INFRA)
1846 #endif // CONFIG_STA_SUPPORT //
1848 // allocate one MAC entry
1849 NdisAcquireSpinLock(&pAd->MacTabLock);
1850 for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++) // skip entry#0 so that "entry index == AID" for fast lookup
1852 // pick up the first available vacancy
1853 if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
1854 (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
1855 (pAd->MacTab.Content[i].ValidAsApCli== FALSE) &&
1856 (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
1859 pEntry = &pAd->MacTab.Content[i];
1860 if (CleanAll == TRUE)
1862 pEntry->MaxSupportedRate = RATE_11;
1863 pEntry->CurrTxRate = RATE_11;
1864 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1865 pEntry->PairwiseKey.KeyLen = 0;
1866 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1870 #ifdef CONFIG_STA_SUPPORT
1871 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1873 pEntry->ValidAsCLI = TRUE;
1874 pEntry->ValidAsWDS = FALSE;
1875 pEntry->ValidAsApCli = FALSE;
1876 pEntry->ValidAsMesh = FALSE;
1877 pEntry->ValidAsDls = FALSE;
1879 #endif // CONFIG_STA_SUPPORT //
1882 pEntry->bIAmBadAtheros = FALSE;
1884 pEntry->CMTimerRunning = FALSE;
1885 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
1886 pEntry->RSNIE_Len = 0;
1887 NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
1888 pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
1890 if (pEntry->ValidAsMesh)
1891 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH);
1892 else if (pEntry->ValidAsApCli)
1893 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI);
1894 else if (pEntry->ValidAsWDS)
1895 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS);
1897 pEntry->apidx = apidx;
1901 #ifdef CONFIG_STA_SUPPORT
1902 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1904 pEntry->AuthMode = pAd->StaCfg.AuthMode;
1905 pEntry->WepStatus = pAd->StaCfg.WepStatus;
1906 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
1908 #endif // CONFIG_STA_SUPPORT //
1911 pEntry->GTKState = REKEY_NEGOTIATING;
1912 pEntry->PairwiseKey.KeyLen = 0;
1913 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1914 pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
1915 pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
1916 COPY_MAC_ADDR(pEntry->Addr, pAddr);
1917 pEntry->Sst = SST_NOT_AUTH;
1918 pEntry->AuthState = AS_NOT_AUTH;
1919 pEntry->Aid = (USHORT)i; //0;
1920 pEntry->CapabilityInfo = 0;
1921 pEntry->PsMode = PWR_ACTIVE;
1922 pEntry->PsQIdleCount = 0;
1923 pEntry->NoDataIdleCount = 0;
1924 pEntry->ContinueTxFailCnt = 0;
1925 InitializeQueueHeader(&pEntry->PsQueue);
1928 pAd->MacTab.Size ++;
1930 // Add this entry into ASIC RX WCID search table
1931 RT28XX_STA_ENTRY_ADD(pAd, pEntry);
1935 DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size));
1940 // add this MAC entry into HASH table
1943 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1944 if (pAd->MacTab.Hash[HashIdx] == NULL)
1946 pAd->MacTab.Hash[HashIdx] = pEntry;
1950 pCurrEntry = pAd->MacTab.Hash[HashIdx];
1951 while (pCurrEntry->pNext != NULL)
1952 pCurrEntry = pCurrEntry->pNext;
1953 pCurrEntry->pNext = pEntry;
1957 NdisReleaseSpinLock(&pAd->MacTabLock);
1962 ==========================================================================
1964 Delete a specified client from MAC table
1965 ==========================================================================
1967 BOOLEAN MacTableDeleteEntry(
1968 IN PRTMP_ADAPTER pAd,
1973 MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
1975 //USHORT offset; // unused variable
1976 //UCHAR j; // unused variable
1978 if (wcid >= MAX_LEN_OF_MAC_TABLE)
1981 NdisAcquireSpinLock(&pAd->MacTabLock);
1983 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1984 //pEntry = pAd->MacTab.Hash[HashIdx];
1985 pEntry = &pAd->MacTab.Content[wcid];
1987 if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh
1990 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1993 // Delete this entry from ASIC on-chip WCID Table
1994 RT28XX_STA_ENTRY_MAC_RESET(pAd, wcid);
1996 #ifdef DOT11_N_SUPPORT
1997 // free resources of BA
1998 BASessionTearDownALL(pAd, pEntry->Aid);
1999 #endif // DOT11_N_SUPPORT //
2003 pProbeEntry = pAd->MacTab.Hash[HashIdx];
2004 ASSERT(pProbeEntry);
2009 if (pProbeEntry == pEntry)
2011 if (pPrevEntry == NULL)
2013 pAd->MacTab.Hash[HashIdx] = pEntry->pNext;
2017 pPrevEntry->pNext = pEntry->pNext;
2022 pPrevEntry = pProbeEntry;
2023 pProbeEntry = pProbeEntry->pNext;
2024 } while (pProbeEntry);
2027 ASSERT(pProbeEntry != NULL);
2029 RT28XX_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
2032 if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
2034 RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
2035 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
2039 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
2040 pAd->MacTab.Size --;
2041 DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size));
2045 printk("\n%s: Impossible Wcid = %d !!!!!\n", __func__, wcid);
2049 NdisReleaseSpinLock(&pAd->MacTabLock);
2051 //Reset operating mode when no Sta.
2052 if (pAd->MacTab.Size == 0)
2054 #ifdef DOT11_N_SUPPORT
2055 pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
2056 #endif // DOT11_N_SUPPORT //
2057 //AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/);
2058 RT28XX_UPDATE_PROTECT(pAd); // edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet
2066 ==========================================================================
2068 This routine reset the entire MAC table. All packets pending in
2069 the power-saving queues are freed here.
2070 ==========================================================================
2073 IN PRTMP_ADAPTER pAd)
2077 DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
2078 //NdisAcquireSpinLock(&pAd->MacTabLock);
2080 for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
2082 if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
2085 #ifdef DOT11_N_SUPPORT
2086 // free resources of BA
2087 BASessionTearDownALL(pAd, i);
2088 #endif // DOT11_N_SUPPORT //
2090 pAd->MacTab.Content[i].ValidAsCLI = FALSE;
2095 NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6);
2096 RT28XX_STA_ENTRY_MAC_RESET(pAd, i);
2099 //AsicDelWcidTab(pAd, i);
2107 ==========================================================================
2110 IRQL = DISPATCH_LEVEL
2112 ==========================================================================
2115 IN PRTMP_ADAPTER pAd,
2116 IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
2118 IN USHORT CapabilityInfo,
2120 IN USHORT ListenIntv)
2122 COPY_MAC_ADDR(AssocReq->Addr, pAddr);
2123 // Add mask to support 802.11b mode only
2124 AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request
2125 AssocReq->Timeout = Timeout;
2126 AssocReq->ListenIntv = ListenIntv;
2131 ==========================================================================
2134 IRQL = DISPATCH_LEVEL
2136 ==========================================================================
2138 VOID DisassocParmFill(
2139 IN PRTMP_ADAPTER pAd,
2140 IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
2144 COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
2145 DisassocReq->Reason = Reason;
2150 ========================================================================
2152 Routine Description:
2153 Check the out going frame, if this is an DHCP or ARP datagram
2154 will be duplicate another frame at low data rate transmit.
2157 pAd Pointer to our adapter
2158 pPacket Pointer to outgoing Ndis frame
2161 TRUE To be duplicate at Low data rate transmit. (1mb)
2164 IRQL = DISPATCH_LEVEL
2168 MAC header + IP Header + UDP Header
2172 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
2174 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
2177 port 0x43 means Bootstrap Protocol, server.
2178 Port 0x44 means Bootstrap Protocol, client.
2180 ========================================================================
2183 BOOLEAN RTMPCheckDHCPFrame(
2184 IN PRTMP_ADAPTER pAd,
2185 IN PNDIS_PACKET pPacket)
2187 PACKET_INFO PacketInfo;
2188 ULONG NumberOfBytesRead = 0;
2189 ULONG CurrentOffset = 0;
2190 PVOID pVirtualAddress = NULL;
2191 UINT NdisBufferLength;
2194 UCHAR ByteOffset36 = 0;
2195 UCHAR ByteOffset38 = 0;
2196 BOOLEAN ReadFirstParm = TRUE;
2198 RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength);
2200 NumberOfBytesRead += NdisBufferLength;
2201 pSrc = (PUCHAR) pVirtualAddress;
2202 Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
2205 // Check DHCP & BOOTP protocol
2207 while (NumberOfBytesRead <= PacketInfo.TotalPacketLength)
2209 if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE))
2211 CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength);
2212 ByteOffset36 = *(pSrc + CurrentOffset);
2213 ReadFirstParm = FALSE;
2216 if (NumberOfBytesRead >= 37)
2218 CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength);
2219 ByteOffset38 = *(pSrc + CurrentOffset);
2226 // Check for DHCP & BOOTP protocol
2227 if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43))
2230 // 2054 (hex 0806) for ARP datagrams
2231 // if this packet is not ARP datagrams, then do nothing
2232 // ARP datagrams will also be duplicate at 1mb broadcast frames
2234 if (Protocol != 0x0806 )
2242 BOOLEAN RTMPCheckEtherType(
2243 IN PRTMP_ADAPTER pAd,
2244 IN PNDIS_PACKET pPacket)
2250 UINT16 srcPort, dstPort;
2251 BOOLEAN status = TRUE;
2254 pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
2255 pktLen = GET_OS_PKT_LEN(pPacket);
2259 RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
2261 // get Ethernet protocol field
2262 TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13];
2264 pSrcBuf += LENGTH_802_3; // Skip the Ethernet Header.
2266 if (TypeLen <= 1500)
2267 { // 802.3, 802.3 LLC
2269 DestMAC(6) + SrcMAC(6) + Lenght(2) +
2270 DSAP(1) + SSAP(1) + Control(1) +
2271 if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
2272 => + SNAP (5, OriginationID(3) + etherType(2))
2274 if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03)
2276 Sniff2BytesFromNdisBuffer(pSrcBuf, 6, &Byte0, &Byte1);
2277 RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
2278 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2279 pSrcBuf += 8; // Skip this LLC/SNAP header
2283 //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.
2287 // If it's a VLAN packet, get the real Type/Length field.
2288 if (TypeLen == 0x8100)
2290 /* 0x8100 means VLAN packets */
2292 /* Dest. MAC Address (6-bytes) +
2293 Source MAC Address (6-bytes) +
2294 Length/Type = 802.1Q Tag Type (2-byte) +
2295 Tag Control Information (2-bytes) +
2296 Length / Type (2-bytes) +
2297 data payload (0-n bytes) +
2299 Frame Check Sequence (4-bytes) */
2301 RTMP_SET_PACKET_VLAN(pPacket, 1);
2302 Sniff2BytesFromNdisBuffer(pSrcBuf, 2, &Byte0, &Byte1);
2303 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2305 pSrcBuf += 4; // Skip the VLAN Header.
2312 ASSERT((pktLen > 34));
2313 if (*(pSrcBuf + 9) == 0x11)
2315 ASSERT((pktLen > 34)); // 14 for ethernet header, 20 for IP header
2317 pSrcBuf += 20; // Skip the IP header
2318 srcPort = OS_NTOHS(*((UINT16 *)pSrcBuf));
2319 dstPort = OS_NTOHS(*((UINT16 *)(pSrcBuf +2)));
2321 if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44))
2322 { //It's a BOOTP/DHCP packet
2323 RTMP_SET_PACKET_DHCP(pPacket, 1);
2331 RTMP_SET_PACKET_DHCP(pPacket, 1);
2337 RTMP_SET_PACKET_EAPOL(pPacket, 1);
2351 VOID Update_Rssi_Sample(
2352 IN PRTMP_ADAPTER pAd,
2353 IN RSSI_SAMPLE *pRssi,
2354 IN PRXWI_STRUC pRxWI)
2356 CHAR rssi0 = pRxWI->RSSI0;
2357 CHAR rssi1 = pRxWI->RSSI1;
2358 CHAR rssi2 = pRxWI->RSSI2;
2362 pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0);
2363 pRssi->AvgRssi0X8 = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
2364 pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
2369 pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1);
2370 pRssi->AvgRssi1X8 = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
2371 pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
2376 pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2);
2377 pRssi->AvgRssi2X8 = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
2378 pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
2384 // Normal legacy Rx packet indication
2385 VOID Indicate_Legacy_Packet(
2386 IN PRTMP_ADAPTER pAd,
2388 IN UCHAR FromWhichBSSID)
2390 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2391 UCHAR Header802_3[LENGTH_802_3];
2393 // 1. get 802.3 Header
2395 // a. pointer pRxBlk->pData to payload
2396 // b. modify pRxBlk->DataSize
2397 #ifdef CONFIG_STA_SUPPORT
2398 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2399 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2400 #endif // CONFIG_STA_SUPPORT //
2402 if (pRxBlk->DataSize > MAX_RX_PKT_LEN)
2405 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2410 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
2413 #ifdef DOT11_N_SUPPORT
2414 if (pAd->CommonCfg.bDisableReordering == 0)
2416 PBA_REC_ENTRY pBAEntry;
2418 UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID;
2419 UCHAR TID = pRxBlk->pRxWI->TID;
2422 #define REORDERING_PACKET_TIMEOUT ((100 * HZ)/1000) // system ticks -- 100 ms
2424 if (Wcid < MAX_LEN_OF_MAC_TABLE)
2426 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
2429 pBAEntry = &pAd->BATable.BARecEntry[Idx];
2430 // update last rx time
2431 NdisGetSystemUpTime(&Now32);
2432 if ((pBAEntry->list.qlen > 0) &&
2433 RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
2436 printk("Indicate_Legacy_Packet():flush reordering_timeout_mpdus! RxWI->Flags=%d, pRxWI.TID=%d, RxD->AMPDU=%d!\n", pRxBlk->Flags, pRxBlk->pRxWI->TID, pRxBlk->RxD.AMPDU);
2437 hex_dump("Dump the legacy Packet:", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), 64);
2438 ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
2443 #endif // DOT11_N_SUPPORT //
2446 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2449 // pass this 802.3 packet to upper layer or forward this packet to WM directly
2451 #ifdef CONFIG_STA_SUPPORT
2452 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2453 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
2454 #endif // CONFIG_STA_SUPPORT //
2459 // Normal, AMPDU or AMSDU
2460 VOID CmmRxnonRalinkFrameIndicate(
2461 IN PRTMP_ADAPTER pAd,
2463 IN UCHAR FromWhichBSSID)
2465 #ifdef DOT11_N_SUPPORT
2466 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
2468 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2471 #endif // DOT11_N_SUPPORT //
2473 #ifdef DOT11_N_SUPPORT
2474 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
2477 Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2480 #endif // DOT11_N_SUPPORT //
2482 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
2488 VOID CmmRxRalinkFrameIndicate(
2489 IN PRTMP_ADAPTER pAd,
2490 IN MAC_TABLE_ENTRY *pEntry,
2492 IN UCHAR FromWhichBSSID)
2494 UCHAR Header802_3[LENGTH_802_3];
2496 UINT16 Payload1Size, Payload2Size;
2498 PNDIS_PACKET pPacket2 = NULL;
2502 Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8);
2504 if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize))
2506 /* skip two byte MSDU2 len */
2508 pRxBlk->DataSize -= 2;
2513 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2517 // get 802.3 Header and remove LLC
2518 #ifdef CONFIG_STA_SUPPORT
2519 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2520 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2521 #endif // CONFIG_STA_SUPPORT //
2524 ASSERT(pRxBlk->pRxPacket);
2526 // Ralink Aggregation frame
2527 pAd->RalinkCounters.OneSecRxAggregationCount ++;
2528 Payload1Size = pRxBlk->DataSize - Msdu2Size;
2529 Payload2Size = Msdu2Size - LENGTH_802_3;
2531 pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
2532 #ifdef CONFIG_STA_SUPPORT
2533 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2534 pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID);
2535 #endif // CONFIG_STA_SUPPORT //
2540 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2544 // update payload size of 1st packet
2545 pRxBlk->DataSize = Payload1Size;
2546 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2548 #ifdef CONFIG_STA_SUPPORT
2549 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2550 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID);
2551 #endif // CONFIG_STA_SUPPORT //
2555 #ifdef CONFIG_STA_SUPPORT
2556 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2557 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
2558 #endif // CONFIG_STA_SUPPORT //
2563 #define RESET_FRAGFRAME(_fragFrame) \
2565 _fragFrame.RxSize = 0; \
2566 _fragFrame.Sequence = 0; \
2567 _fragFrame.LastFrag = 0; \
2568 _fragFrame.Flags = 0; \
2572 PNDIS_PACKET RTMPDeFragmentDataFrame(
2573 IN PRTMP_ADAPTER pAd,
2576 PHEADER_802_11 pHeader = pRxBlk->pHeader;
2577 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2578 UCHAR *pData = pRxBlk->pData;
2579 USHORT DataSize = pRxBlk->DataSize;
2580 PNDIS_PACKET pRetPacket = NULL;
2581 UCHAR *pFragBuffer = NULL;
2582 BOOLEAN bReassDone = FALSE;
2583 UCHAR HeaderRoom = 0;
2588 HeaderRoom = pData - (UCHAR *)pHeader;
2590 // Re-assemble the fragmented packets
2591 if (pHeader->Frag == 0) // Frag. Number is 0 : First frag or only one pkt
2593 // the first pkt of fragment, record it.
2594 if (pHeader->FC.MoreFrag)
2596 ASSERT(pAd->FragFrame.pFragPacket);
2597 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2598 pAd->FragFrame.RxSize = DataSize + HeaderRoom;
2599 NdisMoveMemory(pFragBuffer, pHeader, pAd->FragFrame.RxSize);
2600 pAd->FragFrame.Sequence = pHeader->Sequence;
2601 pAd->FragFrame.LastFrag = pHeader->Frag; // Should be 0
2602 ASSERT(pAd->FragFrame.LastFrag == 0);
2603 goto done; // end of processing this frame
2606 else //Middle & End of fragment
2608 if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
2609 (pHeader->Frag != (pAd->FragFrame.LastFrag + 1)))
2611 // Fragment is not the same sequence or out of fragment number order
2612 // Reset Fragment control blk
2613 RESET_FRAGFRAME(pAd->FragFrame);
2614 DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n"));
2615 goto done; // give up this frame
2617 else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE)
2619 // Fragment frame is too large, it exeeds the maximum frame size.
2620 // Reset Fragment control blk
2621 RESET_FRAGFRAME(pAd->FragFrame);
2622 DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
2623 goto done; // give up this frame
2627 // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.
2628 // In this case, we will dropt it.
2630 if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H)))
2632 DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag));
2633 goto done; // give up this frame
2636 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2638 // concatenate this fragment into the re-assembly buffer
2639 NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize);
2640 pAd->FragFrame.RxSize += DataSize;
2641 pAd->FragFrame.LastFrag = pHeader->Frag; // Update fragment number
2644 if (pHeader->FC.MoreFrag == FALSE)
2651 // always release rx fragmented packet
2652 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2654 // return defragmented packet if packet is reassembled completely
2655 // otherwise return NULL
2658 PNDIS_PACKET pNewFragPacket;
2660 // allocate a new packet buffer for fragment
2661 pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
2665 pRetPacket = pAd->FragFrame.pFragPacket;
2666 pAd->FragFrame.pFragPacket = pNewFragPacket;
2667 pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
2668 pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom;
2669 pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
2670 pRxBlk->pRxPacket = pRetPacket;
2674 RESET_FRAGFRAME(pAd->FragFrame);
2682 VOID Indicate_AMSDU_Packet(
2683 IN PRTMP_ADAPTER pAd,
2685 IN UCHAR FromWhichBSSID)
2689 update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
2690 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
2691 nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize);
2694 VOID Indicate_EAPOL_Packet(
2695 IN PRTMP_ADAPTER pAd,
2697 IN UCHAR FromWhichBSSID)
2699 MAC_TABLE_ENTRY *pEntry = NULL;
2702 #ifdef CONFIG_STA_SUPPORT
2703 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2705 pEntry = &pAd->MacTab.Content[BSSID_WCID];
2706 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
2709 #endif // CONFIG_STA_SUPPORT //
2713 DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
2715 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2720 #define BCN_TBTT_OFFSET 64 //defer 64 us
2721 VOID ReSyncBeaconTime(
2722 IN PRTMP_ADAPTER pAd)
2728 Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
2730 pAd->TbttTickCount++;
2733 // The updated BeaconInterval Value will affect Beacon Interval after two TBTT
2734 // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
2736 if (Offset == (BCN_TBTT_OFFSET-2))
2738 BCN_TIME_CFG_STRUC csr;
2739 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2740 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; // ASIC register in units of 1/16 TU = 64us
2741 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2745 if (Offset == (BCN_TBTT_OFFSET-1))
2747 BCN_TIME_CFG_STRUC csr;
2749 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2750 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU
2751 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);