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));
180 ========================================================================
183 Copy frame from waiting queue into relative ring buffer and set
184 appropriate ASIC register to kick hardware transmit function
187 pAd Pointer to our adapter
188 pBuffer Pointer to memory of outgoing frame
189 Length Size of outgoing management frame
197 IRQL = DISPATCH_LEVEL
201 ========================================================================
203 NDIS_STATUS MlmeHardTransmit(
204 IN PRTMP_ADAPTER pAd,
206 IN PNDIS_PACKET pPacket)
208 if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
211 return NDIS_STATUS_FAILURE;
214 return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
220 NDIS_STATUS MlmeHardTransmitMgmtRing(
221 IN PRTMP_ADAPTER pAd,
223 IN PNDIS_PACKET pPacket)
225 PACKET_INFO PacketInfo;
228 PHEADER_802_11 pHeader_802_11;
229 BOOLEAN bAckRequired, bInsertTimestamp;
231 PTXWI_STRUC pFirstTxWI;
232 MAC_TABLE_ENTRY *pMacEntry = NULL;
234 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
236 // Make sure MGMT ring resource won't be used by other threads
237 // sample, for IRQ LOCK -> SEM LOCK
238 // IrqState = pAd->irq_disabled;
240 RTMP_SEM_LOCK(&pAd->MgmtRingLock);
243 if (pSrcBufVA == NULL)
245 // The buffer shouldn't be NULL
247 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
248 return NDIS_STATUS_FAILURE;
251 #ifdef CONFIG_STA_SUPPORT
252 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
254 // outgoing frame always wakeup PHY to prevent frame lost
255 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
256 AsicForceWakeup(pAd, TRUE);
258 #endif // CONFIG_STA_SUPPORT //
260 pFirstTxWI = (PTXWI_STRUC)(pSrcBufVA + TXINFO_SIZE);
261 pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); //TXWI_SIZE);
263 if (pHeader_802_11->Addr1[0] & 0x01)
265 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
269 MlmeRate = pAd->CommonCfg.MlmeRate;
272 // Verify Mlme rate for a / g bands.
273 if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
276 if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
277 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
279 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
282 #ifdef CONFIG_STA_SUPPORT
283 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
285 // Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode.
286 if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED
287 #ifdef DOT11_N_SUPPORT
288 || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED
289 #endif // DOT11_N_SUPPORT //
292 if (pAd->LatchRfRegs.Channel > 14)
293 pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
295 pAd->CommonCfg.MlmeTransmit.field.MODE = 0;
298 #endif // CONFIG_STA_SUPPORT //
301 // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
302 // Snice it's been set to 0 while on MgtMacHeaderInit
303 // By the way this will cause frame to be send on PWR_SAVE failed.
305 // pHeader_802_11->FC.PwrMgmt = 0; // (pAd->StaCfg.Psm == PWR_SAVE);
307 // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
308 #ifdef CONFIG_STA_SUPPORT
309 // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
310 if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL))
312 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
313 (pHeader_802_11->FC.SubType == SUBTYPE_ACTION))
314 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
316 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
318 #endif // CONFIG_STA_SUPPORT //
320 bInsertTimestamp = FALSE;
321 if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
323 #ifdef CONFIG_STA_SUPPORT
324 //Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue.
325 if ((pAd->OpMode == OPMODE_STA) && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL))
327 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
329 #endif // CONFIG_STA_SUPPORT //
330 bAckRequired = FALSE;
332 else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
335 //pHeader_802_11->Sequence = pAd->Sequence;
337 if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
339 bAckRequired = FALSE;
340 pHeader_802_11->Duration = 0;
345 pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
346 if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
348 bInsertTimestamp = TRUE;
353 pHeader_802_11->Sequence = pAd->Sequence++;
354 if (pAd->Sequence >0xfff)
357 // Before radar detection done, mgmt frame can not be sent but probe req
358 // Because we need to use probe req to trigger driver to send probe req in passive scan
359 if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
360 && (pAd->CommonCfg.bIEEE80211H == 1)
361 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
363 DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
365 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
366 return (NDIS_STATUS_FAILURE);
370 RTMPFrameEndianChange(pAd, (PUCHAR)pHeader_802_11, DIR_WRITE, FALSE);
374 // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
375 // should always has only one ohysical buffer, and the whole frame size equals
376 // to the first scatter buffer size
379 // Initialize TX Descriptor
380 // For inter-frame gap, the number is for this frame and next frame
381 // For MLME rate, we will fix as 2Mb to match other vendor's implement
382 // pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
384 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
385 if (pMacEntry == NULL)
387 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
388 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
392 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
393 bInsertTimestamp, FALSE, bAckRequired, FALSE,
394 0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE),
395 pMacEntry->MaxHTPhyMode.field.MCS, 0,
396 (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
397 IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
401 RTMPWIEndianChange((PUCHAR)pFirstTxWI, TYPE_TXWI);
404 // Now do hardware-depened kick out.
405 HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen);
407 // Make sure to release MGMT ring resource
409 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
410 return NDIS_STATUS_SUCCESS;
414 /********************************************************************************
416 New DeQueue Procedures.
418 ********************************************************************************/
420 #define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \
422 if (bIntContext == FALSE) \
423 RTMP_IRQ_LOCK((lock), IrqFlags); \
426 #define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \
428 if (bIntContext == FALSE) \
429 RTMP_IRQ_UNLOCK((lock), IrqFlags); \
434 static VOID dumpTxBlk(TX_BLK *pTxBlk)
436 NDIS_PACKET *pPacket;
438 PQUEUE_ENTRY pQEntry;
440 printk("Dump TX_BLK Structure:\n");
441 printk("\tTxFrameType=%d!\n", pTxBlk->TxFrameType);
442 printk("\tTotalFrameLen=%d\n", pTxBlk->TotalFrameLen);
443 printk("\tTotalFrameNum=%ld!\n", pTxBlk->TxPacketList.Number);
444 printk("\tTotalFragNum=%d!\n", pTxBlk->TotalFragNum);
445 printk("\tpPacketList=\n");
447 frameNum = pTxBlk->TxPacketList.Number;
449 for(i=0; i < frameNum; i++)
453 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
454 pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
457 pBuf = GET_OS_PKT_DATAPTR(pPacket);
458 printk("\t\t[%d]:ptr=0x%x, Len=%d!\n", i, (UINT32)(GET_OS_PKT_DATAPTR(pPacket)), GET_OS_PKT_LEN(pPacket));
460 for (j =0 ; j < GET_OS_PKT_LEN(pPacket); j++)
462 printk("%02x ", (pBuf[j] & 0xff));
466 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
469 printk("\tWcid=%d!\n", pTxBlk->Wcid);
470 printk("\tapidx=%d!\n", pTxBlk->apidx);
471 printk("----EndOfDump\n");
478 ========================================================================
479 Tx Path design algorithm:
480 Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal),
481 Specific Packet Type. Following show the classification rule and policy for each kinds of packets.
482 Classification Rule=>
483 Multicast: (*addr1 & 0x01) == 0x01
484 Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc.
485 11N Rate : If peer support HT
486 (1).AMPDU -- If TXBA is negotiated.
487 (2).AMSDU -- If AMSDU is capable for both peer and ourself.
488 *). AMSDU can embedded in a AMPDU, but now we didn't support it.
489 (3).Normal -- Other packets which send as 11n rate.
491 B/G Rate : If peer is b/g only.
492 (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6
493 (2).Normal -- Other packets which send as b/g rate.
495 The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
497 Classified Packet Handle Rule=>
499 No ACK, //pTxBlk->bAckRequired = FALSE;
500 No WMM, //pTxBlk->bWMM = FALSE;
501 No piggyback, //pTxBlk->bPiggyBack = FALSE;
502 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
503 Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use
504 the same policy to handle it.
505 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
508 No piggyback, //pTxBlk->bPiggyBack = FALSE;
520 ========================================================================
522 static UCHAR TxPktClassification(
523 IN RTMP_ADAPTER *pAd,
524 IN PNDIS_PACKET pPacket)
526 UCHAR TxFrameType = TX_UNKOWN_FRAME;
528 MAC_TABLE_ENTRY *pMacEntry = NULL;
529 #ifdef DOT11_N_SUPPORT
530 BOOLEAN bHTRate = FALSE;
531 #endif // DOT11_N_SUPPORT //
533 Wcid = RTMP_GET_PACKET_WCID(pPacket);
534 if (Wcid == MCAST_WCID)
535 { // Handle for RA is Broadcast/Multicast Address.
536 return TX_MCAST_FRAME;
539 // Handle for unicast packets
540 pMacEntry = &pAd->MacTab.Content[Wcid];
541 if (RTMP_GET_PACKET_LOWRATE(pPacket))
542 { // It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame
543 TxFrameType = TX_LEGACY_FRAME;
545 #ifdef DOT11_N_SUPPORT
546 else if (IS_HT_RATE(pMacEntry))
547 { // it's a 11n capable packet
549 // Depends on HTPhyMode to check if the peer support the HTRate transmission.
550 // Currently didn't support A-MSDU embedded in A-MPDU
552 if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE))
553 TxFrameType = TX_LEGACY_FRAME;
554 #ifdef UAPSD_AP_SUPPORT
555 else if (RTMP_GET_PACKET_EOSP(pPacket))
556 TxFrameType = TX_LEGACY_FRAME;
557 #endif // UAPSD_AP_SUPPORT //
558 else if((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0)
559 return TX_AMPDU_FRAME;
560 else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED))
561 return TX_AMSDU_FRAME;
563 TxFrameType = TX_LEGACY_FRAME;
565 #endif // DOT11_N_SUPPORT //
567 { // it's a legacy b/g packet.
568 if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) &&
569 (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) &&
570 (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
571 { // if peer support Ralink Aggregation, we use it.
572 TxFrameType = TX_RALINK_FRAME;
576 TxFrameType = TX_LEGACY_FRAME;
580 // Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU.
581 if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) && (TxFrameType == TX_LEGACY_FRAME))
582 TxFrameType = TX_FRAG_FRAME;
588 BOOLEAN RTMP_FillTxBlkInfo(
589 IN RTMP_ADAPTER *pAd,
592 PACKET_INFO PacketInfo;
593 PNDIS_PACKET pPacket;
594 PMAC_TABLE_ENTRY pMacEntry = NULL;
596 pPacket = pTxBlk->pPacket;
597 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
599 pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket);
600 pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket);
601 pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket);
602 pTxBlk->FrameGap = IFS_HTTXOP; // ASIC determine Frame Gap
604 if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket))
605 TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame);
607 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame);
609 // Default to clear this flag
610 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS);
613 if (pTxBlk->Wcid == MCAST_WCID)
615 pTxBlk->pMacEntry = NULL;
617 #ifdef MCAST_RATE_SPECIFIC
618 PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket);
619 if (((*pDA & 0x01) == 0x01) && (*pDA != 0xff))
620 pTxBlk->pTransmit = &pAd->CommonCfg.MCastPhyMode;
622 #endif // MCAST_RATE_SPECIFIC //
623 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
626 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); // AckRequired = FALSE, when broadcast packet in Adhoc mode.
627 //TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate);
628 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag);
629 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
630 if (RTMP_GET_PACKET_MOREDATA(pPacket))
632 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
638 pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
639 pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode;
641 pMacEntry = pTxBlk->pMacEntry;
644 // For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK.
645 if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK)
646 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
648 TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired);
652 #ifdef CONFIG_STA_SUPPORT
653 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
656 // If support WMM, enable it.
657 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
658 CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))
659 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM);
661 #endif // CONFIG_STA_SUPPORT //
664 if (pTxBlk->TxFrameType == TX_LEGACY_FRAME)
666 if ( (RTMP_GET_PACKET_LOWRATE(pPacket)) ||
667 ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1)))
668 { // Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate.
669 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
670 #ifdef DOT11_N_SUPPORT
671 // Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it???
672 if (IS_HT_STA(pTxBlk->pMacEntry) &&
673 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) &&
674 ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)))
676 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
677 TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS);
679 #endif // DOT11_N_SUPPORT //
682 #ifdef DOT11_N_SUPPORT
683 if ( (IS_HT_RATE(pMacEntry) == FALSE) &&
684 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE)))
685 { // Currently piggy-back only support when peer is operate in b/g mode.
686 TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack);
688 #endif // DOT11_N_SUPPORT //
690 if (RTMP_GET_PACKET_MOREDATA(pPacket))
692 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
694 #ifdef UAPSD_AP_SUPPORT
695 if (RTMP_GET_PACKET_EOSP(pPacket))
697 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP);
699 #endif // UAPSD_AP_SUPPORT //
701 else if (pTxBlk->TxFrameType == TX_FRAG_FRAME)
703 TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag);
706 pMacEntry->DebugTxCount++;
713 BOOLEAN CanDoAggregateTransmit(
714 IN RTMP_ADAPTER *pAd,
715 IN NDIS_PACKET *pPacket,
719 //printk("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType);
721 if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
724 if (RTMP_GET_PACKET_DHCP(pPacket) ||
725 RTMP_GET_PACKET_EAPOL(pPacket) ||
726 RTMP_GET_PACKET_WAI(pPacket))
729 if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) &&
730 ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100)))
731 { // For AMSDU, allow the packets with total length < max-amsdu size
735 if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) &&
736 (pTxBlk->TxPacketList.Number == 2))
737 { // For RALINK-Aggregation, allow two frames in one batch.
741 #ifdef CONFIG_STA_SUPPORT
742 if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP
745 #endif // CONFIG_STA_SUPPORT //
752 ========================================================================
755 To do the enqueue operation and extract the first item of waiting
756 list. If a number of available shared memory segments could meet
757 the request of extracted item, the extracted item will be fragmented
758 into shared memory segments.
761 pAd Pointer to our adapter
762 pQueue Pointer to Waiting Queue
767 IRQL = DISPATCH_LEVEL
771 ========================================================================
773 VOID RTMPDeQueuePacket(
774 IN PRTMP_ADAPTER pAd,
775 IN BOOLEAN bIntContext,
776 IN UCHAR QIdx, /* BulkOutPipeId */
777 IN UCHAR Max_Tx_Packets)
779 PQUEUE_ENTRY pEntry = NULL;
780 PNDIS_PACKET pPacket;
781 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
783 PQUEUE_HEADER pQueue;
784 ULONG FreeNumber[NUM_OF_TX_RING];
785 UCHAR QueIdx, sQIdx, eQIdx;
786 unsigned long IrqFlags = 0;
787 BOOLEAN hasTxDesc = FALSE;
793 RtmpDiagStruct *pDiagStruct = &pAd->DiagStruct;
797 if (QIdx == NUM_OF_TX_RING)
800 eQIdx = 3; // 4 ACs, start from 0.
804 sQIdx = eQIdx = QIdx;
807 for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++)
811 RT28XX_START_DEQUEUE(pAd, QueIdx, IrqFlags);
814 firstRound = ((QueIdx == 0) ? TRUE : FALSE);
815 #endif // DBG_DIAGNOSE //
819 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |
820 fRTMP_ADAPTER_RADIO_OFF |
821 fRTMP_ADAPTER_RESET_IN_PROGRESS |
822 fRTMP_ADAPTER_HALT_IN_PROGRESS |
823 fRTMP_ADAPTER_NIC_NOT_EXIST))))
825 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
829 if (Count >= Max_Tx_Packets)
832 DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
833 if (&pAd->TxSwQueue[QueIdx] == NULL)
836 if (firstRound == TRUE)
837 pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][0]++;
838 #endif // DBG_DIAGNOSE //
839 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
844 // probe the Queue Head
845 pQueue = &pAd->TxSwQueue[QueIdx];
846 if ((pEntry = pQueue->Head) == NULL)
848 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
853 NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK));
854 //InitializeQueueHeader(&pTxBlk->TxPacketList); // Didn't need it because we already memzero it.
855 pTxBlk->QueIdx = QueIdx;
857 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
859 // Early check to make sure we have enoguh Tx Resource.
860 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
863 pAd->PrivateInfo.TxRingFullCnt++;
865 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
870 pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
871 pEntry = RemoveHeadQueue(pQueue);
872 pTxBlk->TotalFrameNum++;
873 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
874 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
875 pTxBlk->pPacket = pPacket;
876 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
878 if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME)
880 // Enhance SW Aggregation Mechanism
881 if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType))
883 InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
884 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
889 if((pEntry = pQueue->Head) == NULL)
892 // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation.
893 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
894 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
895 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
896 if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE))
899 //Remove the packet from the TxSwQueue and insert into pTxBlk
900 pEntry = RemoveHeadQueue(pQueue);
902 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
903 pTxBlk->TotalFrameNum++;
904 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
905 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
906 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
909 if (pTxBlk->TxPacketList.Number == 1)
910 pTxBlk->TxFrameType = TX_LEGACY_FRAME;
914 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
917 Count += pTxBlk->TxPacketList.Number;
919 // Do HardTransmit now.
920 #ifdef CONFIG_STA_SUPPORT
921 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
922 Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
923 #endif // CONFIG_STA_SUPPORT //
926 #if 0 // We should not break if HardTransmit failed. Well, at least now we should not!
927 if (Status != NDIS_STATUS_SUCCESS)
929 DBGPRINT(RT_DEBUG_TRACE /*RT_DEBUG_INFO*/,("RTMPHardTransmit return failed!!!\n"));
935 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
939 RTUSBKickBulkOut(pAd);
947 ========================================================================
950 Calculates the duration which is required to transmit out frames
951 with given size and specified rate.
954 pAd Pointer to our adapter
956 Size Frame size in units of byte
959 Duration number in units of usec
962 IRQL = DISPATCH_LEVEL
966 ========================================================================
968 USHORT RTMPCalcDuration(
969 IN PRTMP_ADAPTER pAd,
975 if (Rate < RATE_FIRST_OFDM_RATE) // CCK
977 if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED))
978 Duration = 96; // 72+24 preamble+plcp
980 Duration = 192; // 144+48 preamble+plcp
982 Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]);
983 if ((Size << 4) % RateIdTo500Kbps[Rate])
986 else if (Rate <= RATE_LAST_OFDM_RATE)// OFDM rates
988 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
989 Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
990 if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
995 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
998 return (USHORT)Duration;
1003 ========================================================================
1005 Routine Description:
1006 Calculates the duration which is required to transmit out frames
1007 with given size and specified rate.
1010 pTxWI Pointer to head of each MPDU to HW.
1011 Ack Setting for Ack requirement bit
1012 Fragment Setting for Fragment bit
1013 RetryMode Setting for retry mode
1014 Ifs Setting for IFS gap
1015 Rate Setting for transmit rate
1016 Service Setting for service
1018 TxPreamble Short or Long preamble when using CCK rates
1019 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1024 IRQL = PASSIVE_LEVEL
1025 IRQL = DISPATCH_LEVEL
1027 See also : BASmartHardTransmit() !!!
1029 ========================================================================
1032 IN PRTMP_ADAPTER pAd,
1033 IN PTXWI_STRUC pOutTxWI,
1036 IN BOOLEAN InsTimestamp,
1039 IN BOOLEAN NSeq, // HW new a sequence.
1048 IN HTTRANSMIT_SETTING *pTransmit)
1050 PMAC_TABLE_ENTRY pMac = NULL;
1054 if (WCID < MAX_LEN_OF_MAC_TABLE)
1055 pMac = &pAd->MacTab.Content[WCID];
1058 // Always use Long preamble before verifiation short preamble functionality works well.
1059 // Todo: remove the following line if short preamble functionality works
1061 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1062 NdisZeroMemory(&TxWI, TXWI_SIZE);
1067 pTxWI->CFACK = CFACK;
1068 pTxWI->TS= InsTimestamp;
1069 pTxWI->AMPDU = AMPDU;
1071 pTxWI->txop= Txopmode;
1074 // John tune the performace with Intel Client in 20 MHz performance
1075 #ifdef DOT11_N_SUPPORT
1076 BASize = pAd->CommonCfg.TxBASize;
1080 pTxWI->BAWinSize = BASize;
1081 pTxWI->ShortGI = pTransmit->field.ShortGI;
1082 pTxWI->STBC = pTransmit->field.STBC;
1083 #endif // DOT11_N_SUPPORT //
1085 pTxWI->WirelessCliID = WCID;
1086 pTxWI->MPDUtotalByteCount = Length;
1087 pTxWI->PacketId = PID;
1089 // If CCK or OFDM, BW must be 20
1090 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1091 #ifdef DOT11N_DRAFT3
1093 pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1094 #endif // DOT11N_DRAFT3 //
1096 pTxWI->MCS = pTransmit->field.MCS;
1097 pTxWI->PHYMODE = pTransmit->field.MODE;
1098 pTxWI->CFACK = CfAck;
1100 #ifdef DOT11_N_SUPPORT
1103 if (pAd->CommonCfg.bMIMOPSEnable)
1105 if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1107 // Dynamic MIMO Power Save Mode
1110 else if (pMac->MmpsMode == MMPS_STATIC)
1112 // Static MIMO Power Save Mode
1113 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1120 //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;
1121 if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled))
1123 pTxWI->MpduDensity = 7;
1127 pTxWI->MpduDensity = pMac->MpduDensity;
1130 #endif // DOT11_N_SUPPORT //
1132 pTxWI->PacketId = pTxWI->MCS;
1133 NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC));
1137 VOID RTMPWriteTxWI_Data(
1138 IN PRTMP_ADAPTER pAd,
1139 IN OUT PTXWI_STRUC pTxWI,
1142 HTTRANSMIT_SETTING *pTransmit;
1143 PMAC_TABLE_ENTRY pMacEntry;
1144 #ifdef DOT11_N_SUPPORT
1146 #endif // DOT11_N_SUPPORT //
1151 pTransmit = pTxBlk->pTransmit;
1152 pMacEntry = pTxBlk->pMacEntry;
1156 // Always use Long preamble before verifiation short preamble functionality works well.
1157 // Todo: remove the following line if short preamble functionality works
1159 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1160 NdisZeroMemory(pTxWI, TXWI_SIZE);
1162 pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1163 pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1164 pTxWI->txop = pTxBlk->FrameGap;
1166 #ifdef CONFIG_STA_SUPPORT
1167 #ifdef QOS_DLS_SUPPORT
1169 (pAd->StaCfg.BssType == BSS_INFRA) &&
1170 (pMacEntry->ValidAsDls == TRUE))
1171 pTxWI->WirelessCliID = BSSID_WCID;
1173 #endif // QOS_DLS_SUPPORT //
1174 #endif // CONFIG_STA_SUPPORT //
1175 pTxWI->WirelessCliID = pTxBlk->Wcid;
1177 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1178 pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
1180 // If CCK or OFDM, BW must be 20
1181 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1182 #ifdef DOT11_N_SUPPORT
1183 #ifdef DOT11N_DRAFT3
1185 pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1186 #endif // DOT11N_DRAFT3 //
1187 pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
1189 // John tune the performace with Intel Client in 20 MHz performance
1190 BASize = pAd->CommonCfg.TxBASize;
1191 if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry))
1193 UCHAR RABAOriIdx = 0; //The RA's BA Originator table index.
1195 RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
1196 BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1204 pTxWI->TxBF = pTransmit->field.TxBF;
1205 pTxWI->BAWinSize = BASize;
1206 pTxWI->ShortGI = pTransmit->field.ShortGI;
1207 pTxWI->STBC = pTransmit->field.STBC;
1208 #endif // DOT11_N_SUPPORT //
1210 pTxWI->MCS = pTransmit->field.MCS;
1211 pTxWI->PHYMODE = pTransmit->field.MODE;
1213 #ifdef DOT11_N_SUPPORT
1216 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1218 // Dynamic MIMO Power Save Mode
1221 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1223 // Static MIMO Power Save Mode
1224 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1231 if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled))
1233 pTxWI->MpduDensity = 7;
1237 pTxWI->MpduDensity = pMacEntry->MpduDensity;
1240 #endif // DOT11_N_SUPPORT //
1243 if (pTxBlk->QueIdx== 0)
1245 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1246 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1248 #endif // DBG_DIAGNOSE //
1250 // for rate adapation
1251 pTxWI->PacketId = pTxWI->MCS;
1255 VOID RTMPWriteTxWI_Cache(
1256 IN PRTMP_ADAPTER pAd,
1257 IN OUT PTXWI_STRUC pTxWI,
1260 PHTTRANSMIT_SETTING /*pTxHTPhyMode,*/ pTransmit;
1261 PMAC_TABLE_ENTRY pMacEntry;
1266 pMacEntry = pTxBlk->pMacEntry;
1267 pTransmit = pTxBlk->pTransmit;
1269 if (pMacEntry->bAutoTxRateSwitch)
1271 pTxWI->txop = IFS_HTTXOP;
1273 // If CCK or OFDM, BW must be 20
1274 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1275 pTxWI->ShortGI = pTransmit->field.ShortGI;
1276 pTxWI->STBC = pTransmit->field.STBC;
1278 pTxWI->MCS = pTransmit->field.MCS;
1279 pTxWI->PHYMODE = pTransmit->field.MODE;
1281 // set PID for TxRateSwitching
1282 pTxWI->PacketId = pTransmit->field.MCS;
1285 #ifdef DOT11_N_SUPPORT
1286 pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE);
1289 #ifdef DOT11N_DRAFT3
1291 pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1292 #endif // DOT11N_DRAFT3 //
1294 if (pAd->CommonCfg.bMIMOPSEnable)
1296 // MIMO Power Save Mode
1297 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1299 // Dynamic MIMO Power Save Mode
1302 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1304 // Static MIMO Power Save Mode
1305 if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7))
1312 #endif // DOT11_N_SUPPORT //
1315 if (pTxBlk->QueIdx== 0)
1317 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1318 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1320 #endif // DBG_DIAGNOSE //
1322 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1328 ========================================================================
1330 Routine Description:
1331 Calculates the duration which is required to transmit out frames
1332 with given size and specified rate.
1335 pTxD Pointer to transmit descriptor
1336 Ack Setting for Ack requirement bit
1337 Fragment Setting for Fragment bit
1338 RetryMode Setting for retry mode
1339 Ifs Setting for IFS gap
1340 Rate Setting for transmit rate
1341 Service Setting for service
1343 TxPreamble Short or Long preamble when using CCK rates
1344 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1349 IRQL = PASSIVE_LEVEL
1350 IRQL = DISPATCH_LEVEL
1352 ========================================================================
1354 VOID RTMPWriteTxDescriptor(
1355 IN PRTMP_ADAPTER pAd,
1361 // Always use Long preamble before verifiation short preamble functionality works well.
1362 // Todo: remove the following line if short preamble functionality works
1364 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1366 pTxD->WIV = (bWIV) ? 1: 0;
1367 pTxD->QSEL= (QueueSEL);
1368 //RT2860c?? fixed using EDCA queue for test... We doubt Queue1 has problem. 2006-09-26 Jan
1369 //pTxD->QSEL= FIFO_EDCA;
1370 if (pAd->bGenOneHCCA == TRUE)
1371 pTxD->QSEL= FIFO_HCCA;
1376 // should be called only when -
1377 // 1. MEADIA_CONNECTED
1378 // 2. AGGREGATION_IN_USED
1379 // 3. Fragmentation not in used
1380 // 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible
1381 BOOLEAN TxFrameIsAggregatible(
1382 IN PRTMP_ADAPTER pAd,
1383 IN PUCHAR pPrevAddr1,
1387 // can't aggregate EAPOL (802.1x) frame
1388 if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1391 // can't aggregate multicast/broadcast frame
1392 if (p8023hdr[0] & 0x01)
1395 if (INFRA_ON(pAd)) // must be unicast to AP
1397 else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA
1405 ========================================================================
1407 Routine Description:
1408 Check the MSDU Aggregation policy
1409 1.HT aggregation is A-MSDU
1410 2.legaacy rate aggregation is software aggregation by Ralink.
1418 ========================================================================
1420 BOOLEAN PeerIsAggreOn(
1421 IN PRTMP_ADAPTER pAd,
1423 IN PMAC_TABLE_ENTRY pMacEntry)
1425 ULONG AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
1427 if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags))
1429 #ifdef DOT11_N_SUPPORT
1430 if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX)
1434 #endif // DOT11_N_SUPPORT //
1436 #ifdef AGGREGATION_SUPPORT
1437 if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
1438 { // legacy Ralink Aggregation support
1441 #endif // AGGREGATION_SUPPORT //
1449 ========================================================================
1451 Routine Description:
1452 Check and fine the packet waiting in SW queue with highest priority
1455 pAd Pointer to our adapter
1458 pQueue Pointer to Waiting Queue
1460 IRQL = DISPATCH_LEVEL
1464 ========================================================================
1466 PQUEUE_HEADER RTMPCheckTxSwQueue(
1467 IN PRTMP_ADAPTER pAd,
1472 // 2004-11-15 to be removed. test aggregation only
1473 // if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2))
1476 Number = pAd->TxSwQueue[QID_AC_BK].Number
1477 + pAd->TxSwQueue[QID_AC_BE].Number
1478 + pAd->TxSwQueue[QID_AC_VI].Number
1479 + pAd->TxSwQueue[QID_AC_VO].Number
1480 + pAd->TxSwQueue[QID_HCCA].Number;
1482 if (pAd->TxSwQueue[QID_AC_VO].Head != NULL)
1484 *pQueIdx = QID_AC_VO;
1485 return (&pAd->TxSwQueue[QID_AC_VO]);
1487 else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL)
1489 *pQueIdx = QID_AC_VI;
1490 return (&pAd->TxSwQueue[QID_AC_VI]);
1492 else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL)
1494 *pQueIdx = QID_AC_BE;
1495 return (&pAd->TxSwQueue[QID_AC_BE]);
1497 else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL)
1499 *pQueIdx = QID_AC_BK;
1500 return (&pAd->TxSwQueue[QID_AC_BK]);
1502 else if (pAd->TxSwQueue[QID_HCCA].Head != NULL)
1504 *pQueIdx = QID_HCCA;
1505 return (&pAd->TxSwQueue[QID_HCCA]);
1508 // No packet pending in Tx Sw queue
1509 *pQueIdx = QID_AC_BK;
1517 ========================================================================
1519 Routine Description:
1520 Suspend MSDU transmission
1523 pAd Pointer to our adapter
1530 ========================================================================
1532 VOID RTMPSuspendMsduTransmission(
1533 IN PRTMP_ADAPTER pAd)
1535 DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n"));
1539 // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
1540 // use Lowbound as R66 value on ScanNextChannel(...)
1542 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue);
1544 // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)
1545 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd)));
1546 RTMPSetAGCInitValue(pAd, BW_20);
1548 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1549 //RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000); // abort all TX rings
1554 ========================================================================
1556 Routine Description:
1557 Resume MSDU transmission
1560 pAd Pointer to our adapter
1565 IRQL = DISPATCH_LEVEL
1569 ========================================================================
1571 VOID RTMPResumeMsduTransmission(
1572 IN PRTMP_ADAPTER pAd)
1576 DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
1579 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue);
1581 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1582 // sample, for IRQ LOCK to SEM LOCK
1583 // IrqState = pAd->irq_disabled;
1585 // RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1587 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1591 UINT deaggregate_AMSDU_announce(
1592 IN PRTMP_ADAPTER pAd,
1593 PNDIS_PACKET pPacket,
1598 USHORT SubFrameSize;
1599 PHEADER_802_3 pAMSDUsubheader;
1601 UCHAR Header802_3[14];
1603 PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP;
1604 PNDIS_PACKET pClonePacket;
1610 while (DataSize > LENGTH_802_3)
1615 //hex_dump("subheader", pData, 64);
1616 pAMSDUsubheader = (PHEADER_802_3)pData;
1617 //pData += LENGTH_802_3;
1618 PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8);
1619 SubFrameSize = PayloadSize + LENGTH_802_3;
1622 if ((DataSize < SubFrameSize) || (PayloadSize > 1518 ))
1627 //printk("%d subframe: Size = %d\n", nMSDU, PayloadSize);
1629 pPayload = pData + LENGTH_802_3;
1631 pSA = pData + MAC_ADDR_LEN;
1633 // convert to 802.3 header
1634 CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP);
1636 #ifdef CONFIG_STA_SUPPORT
1637 if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) )
1639 // avoid local heap overflow, use dyanamic allocation
1640 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
1641 memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize);
1642 Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize;
1643 WpaEAPOLKeyAction(pAd, Elem);
1646 #endif // CONFIG_STA_SUPPORT //
1648 #ifdef CONFIG_STA_SUPPORT
1649 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1651 if (pRemovedLLCSNAP)
1653 pPayload -= LENGTH_802_3;
1654 PayloadSize += LENGTH_802_3;
1655 NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3);
1658 #endif // CONFIG_STA_SUPPORT //
1660 pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
1663 #ifdef CONFIG_STA_SUPPORT
1664 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1665 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket));
1666 #endif // CONFIG_STA_SUPPORT //
1670 // A-MSDU has padding to multiple of 4 including subframe header.
1671 // align SubFrameSize up to multiple of 4
1672 SubFrameSize = (SubFrameSize+3)&(~0x3);
1675 if (SubFrameSize > 1528 || SubFrameSize < 32)
1680 if (DataSize > SubFrameSize)
1682 pData += SubFrameSize;
1683 DataSize -= SubFrameSize;
1692 // finally release original rx packet
1693 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1699 UINT BA_Reorder_AMSDU_Annnounce(
1700 IN PRTMP_ADAPTER pAd,
1701 IN PNDIS_PACKET pPacket)
1707 pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
1708 DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
1710 nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
1717 ==========================================================================
1719 Look up the MAC address in the MAC table. Return NULL if not found.
1721 pEntry - pointer to the MAC entry; NULL is not found
1722 ==========================================================================
1724 MAC_TABLE_ENTRY *MacTableLookup(
1725 IN PRTMP_ADAPTER pAd,
1729 MAC_TABLE_ENTRY *pEntry = NULL;
1731 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1732 pEntry = pAd->MacTab.Hash[HashIdx];
1734 while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh))
1736 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1741 pEntry = pEntry->pNext;
1747 MAC_TABLE_ENTRY *MacTableInsertEntry(
1748 IN PRTMP_ADAPTER pAd,
1751 IN BOOLEAN CleanAll)
1755 MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
1758 if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
1762 #ifdef CONFIG_STA_SUPPORT
1763 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1764 if (pAd->StaCfg.BssType == BSS_INFRA)
1766 #endif // CONFIG_STA_SUPPORT //
1768 // allocate one MAC entry
1769 NdisAcquireSpinLock(&pAd->MacTabLock);
1770 for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++) // skip entry#0 so that "entry index == AID" for fast lookup
1772 // pick up the first available vacancy
1773 if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
1774 (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
1775 (pAd->MacTab.Content[i].ValidAsApCli== FALSE) &&
1776 (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
1777 #ifdef CONFIG_STA_SUPPORT
1778 #ifdef QOS_DLS_SUPPORT
1779 && (pAd->MacTab.Content[i].ValidAsDls == FALSE)
1780 #endif // QOS_DLS_SUPPORT //
1781 #endif // CONFIG_STA_SUPPORT //
1784 pEntry = &pAd->MacTab.Content[i];
1785 if (CleanAll == TRUE)
1787 pEntry->MaxSupportedRate = RATE_11;
1788 pEntry->CurrTxRate = RATE_11;
1789 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1790 pEntry->PairwiseKey.KeyLen = 0;
1791 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1793 #ifdef CONFIG_STA_SUPPORT
1794 #ifdef QOS_DLS_SUPPORT
1795 if (apidx >= MIN_NET_DEVICE_FOR_DLS)
1797 pEntry->ValidAsCLI = FALSE;
1798 pEntry->ValidAsWDS = FALSE;
1799 pEntry->ValidAsApCli = FALSE;
1800 pEntry->ValidAsMesh = FALSE;
1801 pEntry->ValidAsDls = TRUE;
1802 pEntry->isCached = FALSE;
1805 #endif // QOS_DLS_SUPPORT //
1806 #endif // CONFIG_STA_SUPPORT //
1809 #ifdef CONFIG_STA_SUPPORT
1810 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1812 pEntry->ValidAsCLI = TRUE;
1813 pEntry->ValidAsWDS = FALSE;
1814 pEntry->ValidAsApCli = FALSE;
1815 pEntry->ValidAsMesh = FALSE;
1816 pEntry->ValidAsDls = FALSE;
1818 #endif // CONFIG_STA_SUPPORT //
1821 pEntry->bIAmBadAtheros = FALSE;
1823 pEntry->CMTimerRunning = FALSE;
1824 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
1825 pEntry->RSNIE_Len = 0;
1826 NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
1827 pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
1829 if (pEntry->ValidAsMesh)
1830 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH);
1831 else if (pEntry->ValidAsApCli)
1832 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI);
1833 else if (pEntry->ValidAsWDS)
1834 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS);
1835 #ifdef CONFIG_STA_SUPPORT
1836 #ifdef QOS_DLS_SUPPORT
1837 else if (pEntry->ValidAsDls)
1838 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_DLS);
1839 #endif // QOS_DLS_SUPPORT //
1840 #endif // CONFIG_STA_SUPPORT //
1842 pEntry->apidx = apidx;
1846 #ifdef CONFIG_STA_SUPPORT
1847 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1849 pEntry->AuthMode = pAd->StaCfg.AuthMode;
1850 pEntry->WepStatus = pAd->StaCfg.WepStatus;
1851 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
1853 #endif // CONFIG_STA_SUPPORT //
1856 pEntry->GTKState = REKEY_NEGOTIATING;
1857 pEntry->PairwiseKey.KeyLen = 0;
1858 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1859 #ifdef CONFIG_STA_SUPPORT
1860 #ifdef QOS_DLS_SUPPORT
1861 if (pEntry->ValidAsDls == TRUE)
1862 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
1863 #endif //QOS_DLS_SUPPORT
1864 #endif // CONFIG_STA_SUPPORT //
1865 pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
1866 pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
1867 COPY_MAC_ADDR(pEntry->Addr, pAddr);
1868 pEntry->Sst = SST_NOT_AUTH;
1869 pEntry->AuthState = AS_NOT_AUTH;
1870 pEntry->Aid = (USHORT)i; //0;
1871 pEntry->CapabilityInfo = 0;
1872 pEntry->PsMode = PWR_ACTIVE;
1873 pEntry->PsQIdleCount = 0;
1874 pEntry->NoDataIdleCount = 0;
1875 pEntry->ContinueTxFailCnt = 0;
1876 InitializeQueueHeader(&pEntry->PsQueue);
1879 pAd->MacTab.Size ++;
1880 // Add this entry into ASIC RX WCID search table
1881 RT28XX_STA_ENTRY_ADD(pAd, pEntry);
1883 DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size));
1888 // add this MAC entry into HASH table
1891 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1892 if (pAd->MacTab.Hash[HashIdx] == NULL)
1894 pAd->MacTab.Hash[HashIdx] = pEntry;
1898 pCurrEntry = pAd->MacTab.Hash[HashIdx];
1899 while (pCurrEntry->pNext != NULL)
1900 pCurrEntry = pCurrEntry->pNext;
1901 pCurrEntry->pNext = pEntry;
1905 NdisReleaseSpinLock(&pAd->MacTabLock);
1910 ==========================================================================
1912 Delete a specified client from MAC table
1913 ==========================================================================
1915 BOOLEAN MacTableDeleteEntry(
1916 IN PRTMP_ADAPTER pAd,
1921 MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
1923 //USHORT offset; // unused variable
1924 //UCHAR j; // unused variable
1926 if (wcid >= MAX_LEN_OF_MAC_TABLE)
1929 NdisAcquireSpinLock(&pAd->MacTabLock);
1931 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1932 //pEntry = pAd->MacTab.Hash[HashIdx];
1933 pEntry = &pAd->MacTab.Content[wcid];
1935 if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh
1936 #ifdef CONFIG_STA_SUPPORT
1937 #ifdef QOS_DLS_SUPPORT
1938 || pEntry->ValidAsDls
1939 #endif // QOS_DLS_SUPPORT //
1940 #endif // CONFIG_STA_SUPPORT //
1943 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1946 // Delete this entry from ASIC on-chip WCID Table
1947 RT28XX_STA_ENTRY_MAC_RESET(pAd, wcid);
1949 #ifdef DOT11_N_SUPPORT
1950 // free resources of BA
1951 BASessionTearDownALL(pAd, pEntry->Aid);
1952 #endif // DOT11_N_SUPPORT //
1956 pProbeEntry = pAd->MacTab.Hash[HashIdx];
1957 ASSERT(pProbeEntry);
1962 if (pProbeEntry == pEntry)
1964 if (pPrevEntry == NULL)
1966 pAd->MacTab.Hash[HashIdx] = pEntry->pNext;
1970 pPrevEntry->pNext = pEntry->pNext;
1975 pPrevEntry = pProbeEntry;
1976 pProbeEntry = pProbeEntry->pNext;
1977 } while (pProbeEntry);
1980 ASSERT(pProbeEntry != NULL);
1982 RT28XX_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
1985 if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
1987 RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
1988 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
1992 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1993 pAd->MacTab.Size --;
1994 DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size));
1998 printk("\n%s: Impossible Wcid = %d !!!!!\n", __func__, wcid);
2002 NdisReleaseSpinLock(&pAd->MacTabLock);
2004 //Reset operating mode when no Sta.
2005 if (pAd->MacTab.Size == 0)
2007 #ifdef DOT11_N_SUPPORT
2008 pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
2009 #endif // DOT11_N_SUPPORT //
2010 AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/);
2018 ==========================================================================
2020 This routine reset the entire MAC table. All packets pending in
2021 the power-saving queues are freed here.
2022 ==========================================================================
2025 IN PRTMP_ADAPTER pAd)
2029 DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
2030 //NdisAcquireSpinLock(&pAd->MacTabLock);
2032 for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
2034 if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
2037 #ifdef DOT11_N_SUPPORT
2038 // free resources of BA
2039 BASessionTearDownALL(pAd, i);
2040 #endif // DOT11_N_SUPPORT //
2042 pAd->MacTab.Content[i].ValidAsCLI = FALSE;
2047 NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6);
2048 RT28XX_STA_ENTRY_MAC_RESET(pAd, i);
2051 //AsicDelWcidTab(pAd, i);
2059 ==========================================================================
2062 IRQL = DISPATCH_LEVEL
2064 ==========================================================================
2067 IN PRTMP_ADAPTER pAd,
2068 IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
2070 IN USHORT CapabilityInfo,
2072 IN USHORT ListenIntv)
2074 COPY_MAC_ADDR(AssocReq->Addr, pAddr);
2075 // Add mask to support 802.11b mode only
2076 AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request
2077 AssocReq->Timeout = Timeout;
2078 AssocReq->ListenIntv = ListenIntv;
2083 ==========================================================================
2086 IRQL = DISPATCH_LEVEL
2088 ==========================================================================
2090 VOID DisassocParmFill(
2091 IN PRTMP_ADAPTER pAd,
2092 IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
2096 COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
2097 DisassocReq->Reason = Reason;
2102 ========================================================================
2104 Routine Description:
2105 Check the out going frame, if this is an DHCP or ARP datagram
2106 will be duplicate another frame at low data rate transmit.
2109 pAd Pointer to our adapter
2110 pPacket Pointer to outgoing Ndis frame
2113 TRUE To be duplicate at Low data rate transmit. (1mb)
2116 IRQL = DISPATCH_LEVEL
2120 MAC header + IP Header + UDP Header
2124 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
2126 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
2129 port 0x43 means Bootstrap Protocol, server.
2130 Port 0x44 means Bootstrap Protocol, client.
2132 ========================================================================
2135 BOOLEAN RTMPCheckDHCPFrame(
2136 IN PRTMP_ADAPTER pAd,
2137 IN PNDIS_PACKET pPacket)
2139 PACKET_INFO PacketInfo;
2140 ULONG NumberOfBytesRead = 0;
2141 ULONG CurrentOffset = 0;
2142 PVOID pVirtualAddress = NULL;
2143 UINT NdisBufferLength;
2146 UCHAR ByteOffset36 = 0;
2147 UCHAR ByteOffset38 = 0;
2148 BOOLEAN ReadFirstParm = TRUE;
2150 RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength);
2152 NumberOfBytesRead += NdisBufferLength;
2153 pSrc = (PUCHAR) pVirtualAddress;
2154 Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
2157 // Check DHCP & BOOTP protocol
2159 while (NumberOfBytesRead <= PacketInfo.TotalPacketLength)
2161 if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE))
2163 CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength);
2164 ByteOffset36 = *(pSrc + CurrentOffset);
2165 ReadFirstParm = FALSE;
2168 if (NumberOfBytesRead >= 37)
2170 CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength);
2171 ByteOffset38 = *(pSrc + CurrentOffset);
2178 // Check for DHCP & BOOTP protocol
2179 if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43))
2182 // 2054 (hex 0806) for ARP datagrams
2183 // if this packet is not ARP datagrams, then do nothing
2184 // ARP datagrams will also be duplicate at 1mb broadcast frames
2186 if (Protocol != 0x0806 )
2194 BOOLEAN RTMPCheckEtherType(
2195 IN PRTMP_ADAPTER pAd,
2196 IN PNDIS_PACKET pPacket)
2202 UINT16 srcPort, dstPort;
2203 BOOLEAN status = TRUE;
2206 pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
2207 pktLen = GET_OS_PKT_LEN(pPacket);
2211 RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
2213 // get Ethernet protocol field
2214 TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13];
2216 pSrcBuf += LENGTH_802_3; // Skip the Ethernet Header.
2218 if (TypeLen <= 1500)
2219 { // 802.3, 802.3 LLC
2221 DestMAC(6) + SrcMAC(6) + Lenght(2) +
2222 DSAP(1) + SSAP(1) + Control(1) +
2223 if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
2224 => + SNAP (5, OriginationID(3) + etherType(2))
2226 if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03)
2228 Sniff2BytesFromNdisBuffer(pSrcBuf, 6, &Byte0, &Byte1);
2229 RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
2230 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2231 pSrcBuf += 8; // Skip this LLC/SNAP header
2235 //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.
2239 // If it's a VLAN packet, get the real Type/Length field.
2240 if (TypeLen == 0x8100)
2242 /* 0x8100 means VLAN packets */
2244 /* Dest. MAC Address (6-bytes) +
2245 Source MAC Address (6-bytes) +
2246 Length/Type = 802.1Q Tag Type (2-byte) +
2247 Tag Control Information (2-bytes) +
2248 Length / Type (2-bytes) +
2249 data payload (0-n bytes) +
2251 Frame Check Sequence (4-bytes) */
2253 RTMP_SET_PACKET_VLAN(pPacket, 1);
2254 Sniff2BytesFromNdisBuffer(pSrcBuf, 2, &Byte0, &Byte1);
2255 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2257 pSrcBuf += 4; // Skip the VLAN Header.
2264 ASSERT((pktLen > 34));
2265 if (*(pSrcBuf + 9) == 0x11)
2267 ASSERT((pktLen > 34)); // 14 for ethernet header, 20 for IP header
2269 pSrcBuf += 20; // Skip the IP header
2270 srcPort = OS_NTOHS(*((UINT16 *)pSrcBuf));
2271 dstPort = OS_NTOHS(*((UINT16 *)(pSrcBuf +2)));
2273 if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44))
2274 { //It's a BOOTP/DHCP packet
2275 RTMP_SET_PACKET_DHCP(pPacket, 1);
2283 RTMP_SET_PACKET_DHCP(pPacket, 1);
2289 RTMP_SET_PACKET_EAPOL(pPacket, 1);
2303 VOID Update_Rssi_Sample(
2304 IN PRTMP_ADAPTER pAd,
2305 IN RSSI_SAMPLE *pRssi,
2306 IN PRXWI_STRUC pRxWI)
2308 CHAR rssi0 = pRxWI->RSSI0;
2309 CHAR rssi1 = pRxWI->RSSI1;
2310 CHAR rssi2 = pRxWI->RSSI2;
2314 pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0);
2315 pRssi->AvgRssi0X8 = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
2316 pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
2321 pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1);
2322 pRssi->AvgRssi1X8 = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
2323 pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
2328 pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2);
2329 pRssi->AvgRssi2X8 = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
2330 pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
2336 // Normal legacy Rx packet indication
2337 VOID Indicate_Legacy_Packet(
2338 IN PRTMP_ADAPTER pAd,
2340 IN UCHAR FromWhichBSSID)
2342 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2343 UCHAR Header802_3[LENGTH_802_3];
2345 // 1. get 802.3 Header
2347 // a. pointer pRxBlk->pData to payload
2348 // b. modify pRxBlk->DataSize
2349 #ifdef CONFIG_STA_SUPPORT
2350 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2351 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2352 #endif // CONFIG_STA_SUPPORT //
2354 if (pRxBlk->DataSize > MAX_RX_PKT_LEN)
2356 #if 0 // sample take off, for multiple card design
2357 static int err_size;
2362 printk("Legacy DataSize = %d\n", pRxBlk->DataSize);
2363 hex_dump("802.3 Header", Header802_3, LENGTH_802_3);
2364 hex_dump("Payload", pRxBlk->pData, 64);
2370 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2375 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
2378 #ifdef DOT11_N_SUPPORT
2379 if (pAd->CommonCfg.bDisableReordering == 0)
2381 PBA_REC_ENTRY pBAEntry;
2383 UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID;
2384 UCHAR TID = pRxBlk->pRxWI->TID;
2387 #define REORDERING_PACKET_TIMEOUT ((100 * HZ)/1000) // system ticks -- 100 ms
2389 if (Wcid < MAX_LEN_OF_MAC_TABLE)
2391 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
2394 pBAEntry = &pAd->BATable.BARecEntry[Idx];
2395 // update last rx time
2396 NdisGetSystemUpTime(&Now32);
2397 if ((pBAEntry->list.qlen > 0) &&
2398 RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
2401 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);
2402 hex_dump("Dump the legacy Packet:", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), 64);
2403 ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
2408 #endif // DOT11_N_SUPPORT //
2411 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2414 // pass this 802.3 packet to upper layer or forward this packet to WM directly
2416 #ifdef CONFIG_STA_SUPPORT
2417 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2418 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
2419 #endif // CONFIG_STA_SUPPORT //
2424 // Normal, AMPDU or AMSDU
2425 VOID CmmRxnonRalinkFrameIndicate(
2426 IN PRTMP_ADAPTER pAd,
2428 IN UCHAR FromWhichBSSID)
2430 #ifdef DOT11_N_SUPPORT
2431 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
2433 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2436 #endif // DOT11_N_SUPPORT //
2438 #ifdef DOT11_N_SUPPORT
2439 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
2442 Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2445 #endif // DOT11_N_SUPPORT //
2447 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
2453 VOID CmmRxRalinkFrameIndicate(
2454 IN PRTMP_ADAPTER pAd,
2455 IN MAC_TABLE_ENTRY *pEntry,
2457 IN UCHAR FromWhichBSSID)
2459 UCHAR Header802_3[LENGTH_802_3];
2461 UINT16 Payload1Size, Payload2Size;
2463 PNDIS_PACKET pPacket2 = NULL;
2467 Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8);
2469 if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize))
2471 /* skip two byte MSDU2 len */
2473 pRxBlk->DataSize -= 2;
2478 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2482 // get 802.3 Header and remove LLC
2483 #ifdef CONFIG_STA_SUPPORT
2484 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2485 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2486 #endif // CONFIG_STA_SUPPORT //
2489 ASSERT(pRxBlk->pRxPacket);
2491 // Ralink Aggregation frame
2492 pAd->RalinkCounters.OneSecRxAggregationCount ++;
2493 Payload1Size = pRxBlk->DataSize - Msdu2Size;
2494 Payload2Size = Msdu2Size - LENGTH_802_3;
2496 pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
2497 #ifdef CONFIG_STA_SUPPORT
2498 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2499 pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID);
2500 #endif // CONFIG_STA_SUPPORT //
2505 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2509 // update payload size of 1st packet
2510 pRxBlk->DataSize = Payload1Size;
2511 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2513 #ifdef CONFIG_STA_SUPPORT
2514 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2515 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID);
2516 #endif // CONFIG_STA_SUPPORT //
2520 #ifdef CONFIG_STA_SUPPORT
2521 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2522 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
2523 #endif // CONFIG_STA_SUPPORT //
2528 #define RESET_FRAGFRAME(_fragFrame) \
2530 _fragFrame.RxSize = 0; \
2531 _fragFrame.Sequence = 0; \
2532 _fragFrame.LastFrag = 0; \
2533 _fragFrame.Flags = 0; \
2537 PNDIS_PACKET RTMPDeFragmentDataFrame(
2538 IN PRTMP_ADAPTER pAd,
2541 PHEADER_802_11 pHeader = pRxBlk->pHeader;
2542 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2543 UCHAR *pData = pRxBlk->pData;
2544 USHORT DataSize = pRxBlk->DataSize;
2545 PNDIS_PACKET pRetPacket = NULL;
2546 UCHAR *pFragBuffer = NULL;
2547 BOOLEAN bReassDone = FALSE;
2548 UCHAR HeaderRoom = 0;
2553 HeaderRoom = pData - (UCHAR *)pHeader;
2555 // Re-assemble the fragmented packets
2556 if (pHeader->Frag == 0) // Frag. Number is 0 : First frag or only one pkt
2558 // the first pkt of fragment, record it.
2559 if (pHeader->FC.MoreFrag)
2561 ASSERT(pAd->FragFrame.pFragPacket);
2562 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2563 pAd->FragFrame.RxSize = DataSize + HeaderRoom;
2564 NdisMoveMemory(pFragBuffer, pHeader, pAd->FragFrame.RxSize);
2565 pAd->FragFrame.Sequence = pHeader->Sequence;
2566 pAd->FragFrame.LastFrag = pHeader->Frag; // Should be 0
2567 ASSERT(pAd->FragFrame.LastFrag == 0);
2568 goto done; // end of processing this frame
2571 else //Middle & End of fragment
2573 if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
2574 (pHeader->Frag != (pAd->FragFrame.LastFrag + 1)))
2576 // Fragment is not the same sequence or out of fragment number order
2577 // Reset Fragment control blk
2578 RESET_FRAGFRAME(pAd->FragFrame);
2579 DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n"));
2580 goto done; // give up this frame
2582 else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE)
2584 // Fragment frame is too large, it exeeds the maximum frame size.
2585 // Reset Fragment control blk
2586 RESET_FRAGFRAME(pAd->FragFrame);
2587 DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
2588 goto done; // give up this frame
2592 // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.
2593 // In this case, we will dropt it.
2595 if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H)))
2597 DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag));
2598 goto done; // give up this frame
2601 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2603 // concatenate this fragment into the re-assembly buffer
2604 NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize);
2605 pAd->FragFrame.RxSize += DataSize;
2606 pAd->FragFrame.LastFrag = pHeader->Frag; // Update fragment number
2609 if (pHeader->FC.MoreFrag == FALSE)
2616 // always release rx fragmented packet
2617 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2619 // return defragmented packet if packet is reassembled completely
2620 // otherwise return NULL
2623 PNDIS_PACKET pNewFragPacket;
2625 // allocate a new packet buffer for fragment
2626 pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
2630 pRetPacket = pAd->FragFrame.pFragPacket;
2631 pAd->FragFrame.pFragPacket = pNewFragPacket;
2632 pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
2633 pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom;
2634 pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
2635 pRxBlk->pRxPacket = pRetPacket;
2639 RESET_FRAGFRAME(pAd->FragFrame);
2647 VOID Indicate_AMSDU_Packet(
2648 IN PRTMP_ADAPTER pAd,
2650 IN UCHAR FromWhichBSSID)
2654 update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
2655 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
2656 nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize);
2659 VOID Indicate_EAPOL_Packet(
2660 IN PRTMP_ADAPTER pAd,
2662 IN UCHAR FromWhichBSSID)
2664 MAC_TABLE_ENTRY *pEntry = NULL;
2667 #ifdef CONFIG_STA_SUPPORT
2668 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2670 pEntry = &pAd->MacTab.Content[BSSID_WCID];
2671 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
2674 #endif // CONFIG_STA_SUPPORT //
2678 DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
2680 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2685 #define BCN_TBTT_OFFSET 64 //defer 64 us
2686 VOID ReSyncBeaconTime(
2687 IN PRTMP_ADAPTER pAd)
2693 Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
2695 pAd->TbttTickCount++;
2698 // The updated BeaconInterval Value will affect Beacon Interval after two TBTT
2699 // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
2701 if (Offset == (BCN_TBTT_OFFSET-2))
2703 BCN_TIME_CFG_STRUC csr;
2704 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2705 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; // ASIC register in units of 1/16 TU = 64us
2706 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2710 if (Offset == (BCN_TBTT_OFFSET-1))
2712 BCN_TIME_CFG_STRUC csr;
2714 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2715 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU
2716 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);