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)
209 #ifdef CARRIER_DETECTION_SUPPORT
210 #endif // CARRIER_DETECTION_SUPPORT //
213 return NDIS_STATUS_FAILURE;
216 return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
222 NDIS_STATUS MlmeHardTransmitMgmtRing(
223 IN PRTMP_ADAPTER pAd,
225 IN PNDIS_PACKET pPacket)
227 PACKET_INFO PacketInfo;
230 PHEADER_802_11 pHeader_802_11;
231 BOOLEAN bAckRequired, bInsertTimestamp;
233 PTXWI_STRUC pFirstTxWI;
234 MAC_TABLE_ENTRY *pMacEntry = NULL;
236 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
238 // Make sure MGMT ring resource won't be used by other threads
239 // sample, for IRQ LOCK -> SEM LOCK
240 // IrqState = pAd->irq_disabled;
242 RTMP_SEM_LOCK(&pAd->MgmtRingLock);
245 if (pSrcBufVA == NULL)
247 // The buffer shouldn't be NULL
249 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
250 return NDIS_STATUS_FAILURE;
253 #ifdef CONFIG_STA_SUPPORT
254 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
256 // outgoing frame always wakeup PHY to prevent frame lost
257 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
258 AsicForceWakeup(pAd, TRUE);
260 #endif // CONFIG_STA_SUPPORT //
262 pFirstTxWI = (PTXWI_STRUC)(pSrcBufVA + TXINFO_SIZE);
263 pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); //TXWI_SIZE);
265 if (pHeader_802_11->Addr1[0] & 0x01)
267 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
271 MlmeRate = pAd->CommonCfg.MlmeRate;
274 // Verify Mlme rate for a / g bands.
275 if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
278 if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
279 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
281 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
284 #ifdef CONFIG_STA_SUPPORT
285 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
287 // Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode.
288 if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED
289 #ifdef DOT11_N_SUPPORT
290 || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED
291 #endif // DOT11_N_SUPPORT //
294 if (pAd->LatchRfRegs.Channel > 14)
295 pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
297 pAd->CommonCfg.MlmeTransmit.field.MODE = 0;
300 #endif // CONFIG_STA_SUPPORT //
303 // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
304 // Snice it's been set to 0 while on MgtMacHeaderInit
305 // By the way this will cause frame to be send on PWR_SAVE failed.
307 // pHeader_802_11->FC.PwrMgmt = 0; // (pAd->StaCfg.Psm == PWR_SAVE);
309 // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
310 #ifdef CONFIG_STA_SUPPORT
311 // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
312 if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL))
314 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
315 (pHeader_802_11->FC.SubType == SUBTYPE_ACTION))
316 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
318 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
320 #endif // CONFIG_STA_SUPPORT //
322 bInsertTimestamp = FALSE;
323 if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
325 #ifdef CONFIG_STA_SUPPORT
326 //Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue.
327 if ((pAd->OpMode == OPMODE_STA) && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL))
329 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
331 #endif // CONFIG_STA_SUPPORT //
332 bAckRequired = FALSE;
334 else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
337 //pHeader_802_11->Sequence = pAd->Sequence;
339 if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
341 bAckRequired = FALSE;
342 pHeader_802_11->Duration = 0;
347 pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
348 if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
350 bInsertTimestamp = TRUE;
355 pHeader_802_11->Sequence = pAd->Sequence++;
356 if (pAd->Sequence >0xfff)
359 // Before radar detection done, mgmt frame can not be sent but probe req
360 // Because we need to use probe req to trigger driver to send probe req in passive scan
361 if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
362 && (pAd->CommonCfg.bIEEE80211H == 1)
363 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
365 DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
367 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
368 return (NDIS_STATUS_FAILURE);
372 RTMPFrameEndianChange(pAd, (PUCHAR)pHeader_802_11, DIR_WRITE, FALSE);
376 // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
377 // should always has only one ohysical buffer, and the whole frame size equals
378 // to the first scatter buffer size
381 // Initialize TX Descriptor
382 // For inter-frame gap, the number is for this frame and next frame
383 // For MLME rate, we will fix as 2Mb to match other vendor's implement
384 // pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
386 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
387 if (pMacEntry == NULL)
389 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
390 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
394 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
395 bInsertTimestamp, FALSE, bAckRequired, FALSE,
396 0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE),
397 pMacEntry->MaxHTPhyMode.field.MCS, 0,
398 (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
399 IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
403 RTMPWIEndianChange((PUCHAR)pFirstTxWI, TYPE_TXWI);
406 // Now do hardware-depened kick out.
407 HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen);
409 // Make sure to release MGMT ring resource
411 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
412 return NDIS_STATUS_SUCCESS;
416 /********************************************************************************
418 New DeQueue Procedures.
420 ********************************************************************************/
422 #define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \
424 if (bIntContext == FALSE) \
425 RTMP_IRQ_LOCK((lock), IrqFlags); \
428 #define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \
430 if (bIntContext == FALSE) \
431 RTMP_IRQ_UNLOCK((lock), IrqFlags); \
436 static VOID dumpTxBlk(TX_BLK *pTxBlk)
438 NDIS_PACKET *pPacket;
440 PQUEUE_ENTRY pQEntry;
442 printk("Dump TX_BLK Structure:\n");
443 printk("\tTxFrameType=%d!\n", pTxBlk->TxFrameType);
444 printk("\tTotalFrameLen=%d\n", pTxBlk->TotalFrameLen);
445 printk("\tTotalFrameNum=%ld!\n", pTxBlk->TxPacketList.Number);
446 printk("\tTotalFragNum=%d!\n", pTxBlk->TotalFragNum);
447 printk("\tpPacketList=\n");
449 frameNum = pTxBlk->TxPacketList.Number;
451 for(i=0; i < frameNum; i++)
455 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
456 pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
459 pBuf = GET_OS_PKT_DATAPTR(pPacket);
460 printk("\t\t[%d]:ptr=0x%x, Len=%d!\n", i, (UINT32)(GET_OS_PKT_DATAPTR(pPacket)), GET_OS_PKT_LEN(pPacket));
462 for (j =0 ; j < GET_OS_PKT_LEN(pPacket); j++)
464 printk("%02x ", (pBuf[j] & 0xff));
468 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
471 printk("\tWcid=%d!\n", pTxBlk->Wcid);
472 printk("\tapidx=%d!\n", pTxBlk->apidx);
473 printk("----EndOfDump\n");
480 ========================================================================
481 Tx Path design algorithm:
482 Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal),
483 Specific Packet Type. Following show the classification rule and policy for each kinds of packets.
484 Classification Rule=>
485 Multicast: (*addr1 & 0x01) == 0x01
486 Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc.
487 11N Rate : If peer support HT
488 (1).AMPDU -- If TXBA is negotiated.
489 (2).AMSDU -- If AMSDU is capable for both peer and ourself.
490 *). AMSDU can embedded in a AMPDU, but now we didn't support it.
491 (3).Normal -- Other packets which send as 11n rate.
493 B/G Rate : If peer is b/g only.
494 (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6
495 (2).Normal -- Other packets which send as b/g rate.
497 The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
499 Classified Packet Handle Rule=>
501 No ACK, //pTxBlk->bAckRequired = FALSE;
502 No WMM, //pTxBlk->bWMM = FALSE;
503 No piggyback, //pTxBlk->bPiggyBack = FALSE;
504 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
505 Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use
506 the same policy to handle it.
507 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
510 No piggyback, //pTxBlk->bPiggyBack = FALSE;
522 ========================================================================
524 static UCHAR TxPktClassification(
525 IN RTMP_ADAPTER *pAd,
526 IN PNDIS_PACKET pPacket)
528 UCHAR TxFrameType = TX_UNKOWN_FRAME;
530 MAC_TABLE_ENTRY *pMacEntry = NULL;
531 #ifdef DOT11_N_SUPPORT
532 BOOLEAN bHTRate = FALSE;
533 #endif // DOT11_N_SUPPORT //
535 Wcid = RTMP_GET_PACKET_WCID(pPacket);
536 if (Wcid == MCAST_WCID)
537 { // Handle for RA is Broadcast/Multicast Address.
538 return TX_MCAST_FRAME;
541 // Handle for unicast packets
542 pMacEntry = &pAd->MacTab.Content[Wcid];
543 if (RTMP_GET_PACKET_LOWRATE(pPacket))
544 { // It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame
545 TxFrameType = TX_LEGACY_FRAME;
547 #ifdef DOT11_N_SUPPORT
548 else if (IS_HT_RATE(pMacEntry))
549 { // it's a 11n capable packet
551 // Depends on HTPhyMode to check if the peer support the HTRate transmission.
552 // Currently didn't support A-MSDU embedded in A-MPDU
554 if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE))
555 TxFrameType = TX_LEGACY_FRAME;
556 #ifdef UAPSD_AP_SUPPORT
557 else if (RTMP_GET_PACKET_EOSP(pPacket))
558 TxFrameType = TX_LEGACY_FRAME;
559 #endif // UAPSD_AP_SUPPORT //
560 else if((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0)
561 return TX_AMPDU_FRAME;
562 else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED))
563 return TX_AMSDU_FRAME;
565 TxFrameType = TX_LEGACY_FRAME;
567 #endif // DOT11_N_SUPPORT //
569 { // it's a legacy b/g packet.
570 if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) &&
571 (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) &&
572 (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
573 { // if peer support Ralink Aggregation, we use it.
574 TxFrameType = TX_RALINK_FRAME;
578 TxFrameType = TX_LEGACY_FRAME;
582 // Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU.
583 if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) && (TxFrameType == TX_LEGACY_FRAME))
584 TxFrameType = TX_FRAG_FRAME;
590 BOOLEAN RTMP_FillTxBlkInfo(
591 IN RTMP_ADAPTER *pAd,
594 PACKET_INFO PacketInfo;
595 PNDIS_PACKET pPacket;
596 PMAC_TABLE_ENTRY pMacEntry = NULL;
598 pPacket = pTxBlk->pPacket;
599 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
601 pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket);
602 pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket);
603 pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket);
604 pTxBlk->FrameGap = IFS_HTTXOP; // ASIC determine Frame Gap
606 if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket))
607 TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame);
609 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame);
611 // Default to clear this flag
612 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS);
615 if (pTxBlk->Wcid == MCAST_WCID)
617 pTxBlk->pMacEntry = NULL;
619 #ifdef MCAST_RATE_SPECIFIC
620 PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket);
621 if (((*pDA & 0x01) == 0x01) && (*pDA != 0xff))
622 pTxBlk->pTransmit = &pAd->CommonCfg.MCastPhyMode;
624 #endif // MCAST_RATE_SPECIFIC //
625 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
628 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); // AckRequired = FALSE, when broadcast packet in Adhoc mode.
629 //TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate);
630 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag);
631 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
632 if (RTMP_GET_PACKET_MOREDATA(pPacket))
634 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
640 pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
641 pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode;
643 pMacEntry = pTxBlk->pMacEntry;
646 // For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK.
647 if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK)
648 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
650 TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired);
654 #ifdef CONFIG_STA_SUPPORT
655 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
658 // If support WMM, enable it.
659 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
660 CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))
661 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM);
663 #endif // CONFIG_STA_SUPPORT //
666 if (pTxBlk->TxFrameType == TX_LEGACY_FRAME)
668 if ( (RTMP_GET_PACKET_LOWRATE(pPacket)) ||
669 ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1)))
670 { // Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate.
671 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
672 #ifdef DOT11_N_SUPPORT
673 // Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it???
674 if (IS_HT_STA(pTxBlk->pMacEntry) &&
675 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) &&
676 ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)))
678 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
679 TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS);
681 #endif // DOT11_N_SUPPORT //
684 #ifdef DOT11_N_SUPPORT
685 if ( (IS_HT_RATE(pMacEntry) == FALSE) &&
686 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE)))
687 { // Currently piggy-back only support when peer is operate in b/g mode.
688 TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack);
690 #endif // DOT11_N_SUPPORT //
692 if (RTMP_GET_PACKET_MOREDATA(pPacket))
694 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
696 #ifdef UAPSD_AP_SUPPORT
697 if (RTMP_GET_PACKET_EOSP(pPacket))
699 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP);
701 #endif // UAPSD_AP_SUPPORT //
703 else if (pTxBlk->TxFrameType == TX_FRAG_FRAME)
705 TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag);
708 pMacEntry->DebugTxCount++;
718 BOOLEAN CanDoAggregateTransmit(
719 IN RTMP_ADAPTER *pAd,
720 IN NDIS_PACKET *pPacket,
724 //printk("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType);
726 if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
729 if (RTMP_GET_PACKET_DHCP(pPacket) ||
730 RTMP_GET_PACKET_EAPOL(pPacket) ||
731 RTMP_GET_PACKET_WAI(pPacket))
734 if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) &&
735 ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100)))
736 { // For AMSDU, allow the packets with total length < max-amsdu size
740 if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) &&
741 (pTxBlk->TxPacketList.Number == 2))
742 { // For RALINK-Aggregation, allow two frames in one batch.
746 #ifdef CONFIG_STA_SUPPORT
747 if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP
750 #endif // CONFIG_STA_SUPPORT //
757 ========================================================================
760 To do the enqueue operation and extract the first item of waiting
761 list. If a number of available shared memory segments could meet
762 the request of extracted item, the extracted item will be fragmented
763 into shared memory segments.
766 pAd Pointer to our adapter
767 pQueue Pointer to Waiting Queue
772 IRQL = DISPATCH_LEVEL
776 ========================================================================
778 VOID RTMPDeQueuePacket(
779 IN PRTMP_ADAPTER pAd,
780 IN BOOLEAN bIntContext,
781 IN UCHAR QIdx, /* BulkOutPipeId */
782 IN UCHAR Max_Tx_Packets)
784 PQUEUE_ENTRY pEntry = NULL;
785 PNDIS_PACKET pPacket;
786 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
788 PQUEUE_HEADER pQueue;
789 ULONG FreeNumber[NUM_OF_TX_RING];
790 UCHAR QueIdx, sQIdx, eQIdx;
791 unsigned long IrqFlags = 0;
792 BOOLEAN hasTxDesc = FALSE;
798 RtmpDiagStruct *pDiagStruct = &pAd->DiagStruct;
802 if (QIdx == NUM_OF_TX_RING)
805 eQIdx = 3; // 4 ACs, start from 0.
809 sQIdx = eQIdx = QIdx;
812 for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++)
816 RT28XX_START_DEQUEUE(pAd, QueIdx, IrqFlags);
819 firstRound = ((QueIdx == 0) ? TRUE : FALSE);
820 #endif // DBG_DIAGNOSE //
824 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |
825 fRTMP_ADAPTER_RADIO_OFF |
826 fRTMP_ADAPTER_RESET_IN_PROGRESS |
827 fRTMP_ADAPTER_HALT_IN_PROGRESS |
828 fRTMP_ADAPTER_NIC_NOT_EXIST))))
830 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
834 if (Count >= Max_Tx_Packets)
837 DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
838 if (&pAd->TxSwQueue[QueIdx] == NULL)
841 if (firstRound == TRUE)
842 pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][0]++;
843 #endif // DBG_DIAGNOSE //
844 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
849 // probe the Queue Head
850 pQueue = &pAd->TxSwQueue[QueIdx];
851 if ((pEntry = pQueue->Head) == NULL)
853 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
858 NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK));
859 //InitializeQueueHeader(&pTxBlk->TxPacketList); // Didn't need it because we already memzero it.
860 pTxBlk->QueIdx = QueIdx;
862 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
864 // Early check to make sure we have enoguh Tx Resource.
865 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
868 pAd->PrivateInfo.TxRingFullCnt++;
870 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
875 pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
876 pEntry = RemoveHeadQueue(pQueue);
877 pTxBlk->TotalFrameNum++;
878 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
879 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
880 pTxBlk->pPacket = pPacket;
881 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
883 if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME)
885 // Enhance SW Aggregation Mechanism
886 if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType))
888 InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
889 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
894 if((pEntry = pQueue->Head) == NULL)
897 // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation.
898 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
899 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
900 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
901 if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE))
904 //Remove the packet from the TxSwQueue and insert into pTxBlk
905 pEntry = RemoveHeadQueue(pQueue);
907 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
908 pTxBlk->TotalFrameNum++;
909 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
910 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
911 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
914 if (pTxBlk->TxPacketList.Number == 1)
915 pTxBlk->TxFrameType = TX_LEGACY_FRAME;
919 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
922 Count += pTxBlk->TxPacketList.Number;
924 // Do HardTransmit now.
925 #ifdef CONFIG_STA_SUPPORT
926 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
927 Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
928 #endif // CONFIG_STA_SUPPORT //
931 #if 0 // We should not break if HardTransmit failed. Well, at least now we should not!
932 if (Status != NDIS_STATUS_SUCCESS)
934 DBGPRINT(RT_DEBUG_TRACE /*RT_DEBUG_INFO*/,("RTMPHardTransmit return failed!!!\n"));
940 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
944 RTUSBKickBulkOut(pAd);
948 if ((pAd->blockQueueTab[QueIdx].SwTxQueueBlockFlag == TRUE)
949 && (pAd->TxSwQueue[QueIdx].Number < 1))
951 releaseNetIf(&pAd->blockQueueTab[QueIdx]);
953 #endif // BLOCK_NET_IF //
961 ========================================================================
964 Calculates the duration which is required to transmit out frames
965 with given size and specified rate.
968 pAd Pointer to our adapter
970 Size Frame size in units of byte
973 Duration number in units of usec
976 IRQL = DISPATCH_LEVEL
980 ========================================================================
982 USHORT RTMPCalcDuration(
983 IN PRTMP_ADAPTER pAd,
989 if (Rate < RATE_FIRST_OFDM_RATE) // CCK
991 if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED))
992 Duration = 96; // 72+24 preamble+plcp
994 Duration = 192; // 144+48 preamble+plcp
996 Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]);
997 if ((Size << 4) % RateIdTo500Kbps[Rate])
1000 else if (Rate <= RATE_LAST_OFDM_RATE)// OFDM rates
1002 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
1003 Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
1004 if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
1009 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
1012 return (USHORT)Duration;
1017 ========================================================================
1019 Routine Description:
1020 Calculates the duration which is required to transmit out frames
1021 with given size and specified rate.
1024 pTxWI Pointer to head of each MPDU to HW.
1025 Ack Setting for Ack requirement bit
1026 Fragment Setting for Fragment bit
1027 RetryMode Setting for retry mode
1028 Ifs Setting for IFS gap
1029 Rate Setting for transmit rate
1030 Service Setting for service
1032 TxPreamble Short or Long preamble when using CCK rates
1033 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1038 IRQL = PASSIVE_LEVEL
1039 IRQL = DISPATCH_LEVEL
1041 See also : BASmartHardTransmit() !!!
1043 ========================================================================
1046 IN PRTMP_ADAPTER pAd,
1047 IN PTXWI_STRUC pOutTxWI,
1050 IN BOOLEAN InsTimestamp,
1053 IN BOOLEAN NSeq, // HW new a sequence.
1062 IN HTTRANSMIT_SETTING *pTransmit)
1064 PMAC_TABLE_ENTRY pMac = NULL;
1068 if (WCID < MAX_LEN_OF_MAC_TABLE)
1069 pMac = &pAd->MacTab.Content[WCID];
1072 // Always use Long preamble before verifiation short preamble functionality works well.
1073 // Todo: remove the following line if short preamble functionality works
1075 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1076 NdisZeroMemory(&TxWI, TXWI_SIZE);
1081 pTxWI->CFACK = CFACK;
1082 pTxWI->TS= InsTimestamp;
1083 pTxWI->AMPDU = AMPDU;
1085 pTxWI->txop= Txopmode;
1088 // John tune the performace with Intel Client in 20 MHz performance
1089 #ifdef DOT11_N_SUPPORT
1090 BASize = pAd->CommonCfg.TxBASize;
1094 pTxWI->BAWinSize = BASize;
1095 pTxWI->ShortGI = pTransmit->field.ShortGI;
1096 pTxWI->STBC = pTransmit->field.STBC;
1097 #endif // DOT11_N_SUPPORT //
1099 pTxWI->WirelessCliID = WCID;
1100 pTxWI->MPDUtotalByteCount = Length;
1101 pTxWI->PacketId = PID;
1103 // If CCK or OFDM, BW must be 20
1104 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1105 #ifdef DOT11N_DRAFT3
1107 pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1108 #endif // DOT11N_DRAFT3 //
1110 pTxWI->MCS = pTransmit->field.MCS;
1111 pTxWI->PHYMODE = pTransmit->field.MODE;
1112 pTxWI->CFACK = CfAck;
1114 #ifdef DOT11_N_SUPPORT
1117 if (pAd->CommonCfg.bMIMOPSEnable)
1119 if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1121 // Dynamic MIMO Power Save Mode
1124 else if (pMac->MmpsMode == MMPS_STATIC)
1126 // Static MIMO Power Save Mode
1127 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1134 //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;
1135 if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled))
1137 pTxWI->MpduDensity = 7;
1141 pTxWI->MpduDensity = pMac->MpduDensity;
1144 #endif // DOT11_N_SUPPORT //
1146 pTxWI->PacketId = pTxWI->MCS;
1147 NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC));
1151 VOID RTMPWriteTxWI_Data(
1152 IN PRTMP_ADAPTER pAd,
1153 IN OUT PTXWI_STRUC pTxWI,
1156 HTTRANSMIT_SETTING *pTransmit;
1157 PMAC_TABLE_ENTRY pMacEntry;
1158 #ifdef DOT11_N_SUPPORT
1160 #endif // DOT11_N_SUPPORT //
1165 pTransmit = pTxBlk->pTransmit;
1166 pMacEntry = pTxBlk->pMacEntry;
1170 // Always use Long preamble before verifiation short preamble functionality works well.
1171 // Todo: remove the following line if short preamble functionality works
1173 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1174 NdisZeroMemory(pTxWI, TXWI_SIZE);
1176 pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1177 pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1178 pTxWI->txop = pTxBlk->FrameGap;
1180 #ifdef CONFIG_STA_SUPPORT
1181 #ifdef QOS_DLS_SUPPORT
1183 (pAd->StaCfg.BssType == BSS_INFRA) &&
1184 (pMacEntry->ValidAsDls == TRUE))
1185 pTxWI->WirelessCliID = BSSID_WCID;
1187 #endif // QOS_DLS_SUPPORT //
1188 #endif // CONFIG_STA_SUPPORT //
1189 pTxWI->WirelessCliID = pTxBlk->Wcid;
1191 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1192 pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
1194 // If CCK or OFDM, BW must be 20
1195 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1196 #ifdef DOT11_N_SUPPORT
1197 #ifdef DOT11N_DRAFT3
1199 pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1200 #endif // DOT11N_DRAFT3 //
1201 pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
1203 // John tune the performace with Intel Client in 20 MHz performance
1204 BASize = pAd->CommonCfg.TxBASize;
1205 if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry))
1207 UCHAR RABAOriIdx = 0; //The RA's BA Originator table index.
1209 RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
1210 BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1218 pTxWI->TxBF = pTransmit->field.TxBF;
1219 pTxWI->BAWinSize = BASize;
1220 pTxWI->ShortGI = pTransmit->field.ShortGI;
1221 pTxWI->STBC = pTransmit->field.STBC;
1222 #endif // DOT11_N_SUPPORT //
1224 pTxWI->MCS = pTransmit->field.MCS;
1225 pTxWI->PHYMODE = pTransmit->field.MODE;
1227 #ifdef DOT11_N_SUPPORT
1230 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1232 // Dynamic MIMO Power Save Mode
1235 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1237 // Static MIMO Power Save Mode
1238 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1245 if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled))
1247 pTxWI->MpduDensity = 7;
1251 pTxWI->MpduDensity = pMacEntry->MpduDensity;
1254 #endif // DOT11_N_SUPPORT //
1257 if (pTxBlk->QueIdx== 0)
1259 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1260 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1262 #endif // DBG_DIAGNOSE //
1264 // for rate adapation
1265 pTxWI->PacketId = pTxWI->MCS;
1269 VOID RTMPWriteTxWI_Cache(
1270 IN PRTMP_ADAPTER pAd,
1271 IN OUT PTXWI_STRUC pTxWI,
1274 PHTTRANSMIT_SETTING /*pTxHTPhyMode,*/ pTransmit;
1275 PMAC_TABLE_ENTRY pMacEntry;
1280 pMacEntry = pTxBlk->pMacEntry;
1281 pTransmit = pTxBlk->pTransmit;
1283 if (pMacEntry->bAutoTxRateSwitch)
1285 pTxWI->txop = IFS_HTTXOP;
1287 // If CCK or OFDM, BW must be 20
1288 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1289 pTxWI->ShortGI = pTransmit->field.ShortGI;
1290 pTxWI->STBC = pTransmit->field.STBC;
1292 pTxWI->MCS = pTransmit->field.MCS;
1293 pTxWI->PHYMODE = pTransmit->field.MODE;
1295 // set PID for TxRateSwitching
1296 pTxWI->PacketId = pTransmit->field.MCS;
1299 #ifdef DOT11_N_SUPPORT
1300 pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE);
1303 #ifdef DOT11N_DRAFT3
1305 pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1306 #endif // DOT11N_DRAFT3 //
1308 if (pAd->CommonCfg.bMIMOPSEnable)
1310 // MIMO Power Save Mode
1311 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1313 // Dynamic MIMO Power Save Mode
1316 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1318 // Static MIMO Power Save Mode
1319 if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7))
1326 #endif // DOT11_N_SUPPORT //
1329 if (pTxBlk->QueIdx== 0)
1331 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1332 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1334 #endif // DBG_DIAGNOSE //
1336 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1342 ========================================================================
1344 Routine Description:
1345 Calculates the duration which is required to transmit out frames
1346 with given size and specified rate.
1349 pTxD Pointer to transmit descriptor
1350 Ack Setting for Ack requirement bit
1351 Fragment Setting for Fragment bit
1352 RetryMode Setting for retry mode
1353 Ifs Setting for IFS gap
1354 Rate Setting for transmit rate
1355 Service Setting for service
1357 TxPreamble Short or Long preamble when using CCK rates
1358 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1363 IRQL = PASSIVE_LEVEL
1364 IRQL = DISPATCH_LEVEL
1366 ========================================================================
1368 VOID RTMPWriteTxDescriptor(
1369 IN PRTMP_ADAPTER pAd,
1375 // Always use Long preamble before verifiation short preamble functionality works well.
1376 // Todo: remove the following line if short preamble functionality works
1378 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1380 pTxD->WIV = (bWIV) ? 1: 0;
1381 pTxD->QSEL= (QueueSEL);
1382 //RT2860c?? fixed using EDCA queue for test... We doubt Queue1 has problem. 2006-09-26 Jan
1383 //pTxD->QSEL= FIFO_EDCA;
1384 if (pAd->bGenOneHCCA == TRUE)
1385 pTxD->QSEL= FIFO_HCCA;
1390 // should be called only when -
1391 // 1. MEADIA_CONNECTED
1392 // 2. AGGREGATION_IN_USED
1393 // 3. Fragmentation not in used
1394 // 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible
1395 BOOLEAN TxFrameIsAggregatible(
1396 IN PRTMP_ADAPTER pAd,
1397 IN PUCHAR pPrevAddr1,
1401 // can't aggregate EAPOL (802.1x) frame
1402 if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1405 // can't aggregate multicast/broadcast frame
1406 if (p8023hdr[0] & 0x01)
1409 if (INFRA_ON(pAd)) // must be unicast to AP
1411 else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA
1419 ========================================================================
1421 Routine Description:
1422 Check the MSDU Aggregation policy
1423 1.HT aggregation is A-MSDU
1424 2.legaacy rate aggregation is software aggregation by Ralink.
1432 ========================================================================
1434 BOOLEAN PeerIsAggreOn(
1435 IN PRTMP_ADAPTER pAd,
1437 IN PMAC_TABLE_ENTRY pMacEntry)
1439 ULONG AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
1441 if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags))
1443 #ifdef DOT11_N_SUPPORT
1444 if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX)
1448 #endif // DOT11_N_SUPPORT //
1450 #ifdef AGGREGATION_SUPPORT
1451 if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
1452 { // legacy Ralink Aggregation support
1455 #endif // AGGREGATION_SUPPORT //
1463 ========================================================================
1465 Routine Description:
1466 Check and fine the packet waiting in SW queue with highest priority
1469 pAd Pointer to our adapter
1472 pQueue Pointer to Waiting Queue
1474 IRQL = DISPATCH_LEVEL
1478 ========================================================================
1480 PQUEUE_HEADER RTMPCheckTxSwQueue(
1481 IN PRTMP_ADAPTER pAd,
1486 // 2004-11-15 to be removed. test aggregation only
1487 // if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2))
1490 Number = pAd->TxSwQueue[QID_AC_BK].Number
1491 + pAd->TxSwQueue[QID_AC_BE].Number
1492 + pAd->TxSwQueue[QID_AC_VI].Number
1493 + pAd->TxSwQueue[QID_AC_VO].Number
1494 + pAd->TxSwQueue[QID_HCCA].Number;
1496 if (pAd->TxSwQueue[QID_AC_VO].Head != NULL)
1498 *pQueIdx = QID_AC_VO;
1499 return (&pAd->TxSwQueue[QID_AC_VO]);
1501 else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL)
1503 *pQueIdx = QID_AC_VI;
1504 return (&pAd->TxSwQueue[QID_AC_VI]);
1506 else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL)
1508 *pQueIdx = QID_AC_BE;
1509 return (&pAd->TxSwQueue[QID_AC_BE]);
1511 else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL)
1513 *pQueIdx = QID_AC_BK;
1514 return (&pAd->TxSwQueue[QID_AC_BK]);
1516 else if (pAd->TxSwQueue[QID_HCCA].Head != NULL)
1518 *pQueIdx = QID_HCCA;
1519 return (&pAd->TxSwQueue[QID_HCCA]);
1522 // No packet pending in Tx Sw queue
1523 *pQueIdx = QID_AC_BK;
1531 ========================================================================
1533 Routine Description:
1534 Suspend MSDU transmission
1537 pAd Pointer to our adapter
1544 ========================================================================
1546 VOID RTMPSuspendMsduTransmission(
1547 IN PRTMP_ADAPTER pAd)
1549 DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n"));
1553 // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
1554 // use Lowbound as R66 value on ScanNextChannel(...)
1556 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue);
1558 // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)
1559 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd)));
1560 RTMPSetAGCInitValue(pAd, BW_20);
1562 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1563 //RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000); // abort all TX rings
1568 ========================================================================
1570 Routine Description:
1571 Resume MSDU transmission
1574 pAd Pointer to our adapter
1579 IRQL = DISPATCH_LEVEL
1583 ========================================================================
1585 VOID RTMPResumeMsduTransmission(
1586 IN PRTMP_ADAPTER pAd)
1590 DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
1593 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue);
1595 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1596 // sample, for IRQ LOCK to SEM LOCK
1597 // IrqState = pAd->irq_disabled;
1599 // RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1601 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1605 UINT deaggregate_AMSDU_announce(
1606 IN PRTMP_ADAPTER pAd,
1607 PNDIS_PACKET pPacket,
1612 USHORT SubFrameSize;
1613 PHEADER_802_3 pAMSDUsubheader;
1615 UCHAR Header802_3[14];
1617 PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP;
1618 PNDIS_PACKET pClonePacket;
1624 while (DataSize > LENGTH_802_3)
1629 //hex_dump("subheader", pData, 64);
1630 pAMSDUsubheader = (PHEADER_802_3)pData;
1631 //pData += LENGTH_802_3;
1632 PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8);
1633 SubFrameSize = PayloadSize + LENGTH_802_3;
1636 if ((DataSize < SubFrameSize) || (PayloadSize > 1518 ))
1641 //printk("%d subframe: Size = %d\n", nMSDU, PayloadSize);
1643 pPayload = pData + LENGTH_802_3;
1645 pSA = pData + MAC_ADDR_LEN;
1647 // convert to 802.3 header
1648 CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP);
1650 #ifdef CONFIG_STA_SUPPORT
1651 if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) )
1653 // avoid local heap overflow, use dyanamic allocation
1654 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
1655 memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize);
1656 Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize;
1657 WpaEAPOLKeyAction(pAd, Elem);
1660 #endif // CONFIG_STA_SUPPORT //
1662 #ifdef CONFIG_STA_SUPPORT
1663 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1665 if (pRemovedLLCSNAP)
1667 pPayload -= LENGTH_802_3;
1668 PayloadSize += LENGTH_802_3;
1669 NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3);
1672 #endif // CONFIG_STA_SUPPORT //
1674 pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
1677 #ifdef CONFIG_STA_SUPPORT
1678 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1679 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket));
1680 #endif // CONFIG_STA_SUPPORT //
1684 // A-MSDU has padding to multiple of 4 including subframe header.
1685 // align SubFrameSize up to multiple of 4
1686 SubFrameSize = (SubFrameSize+3)&(~0x3);
1689 if (SubFrameSize > 1528 || SubFrameSize < 32)
1694 if (DataSize > SubFrameSize)
1696 pData += SubFrameSize;
1697 DataSize -= SubFrameSize;
1706 // finally release original rx packet
1707 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1713 UINT BA_Reorder_AMSDU_Annnounce(
1714 IN PRTMP_ADAPTER pAd,
1715 IN PNDIS_PACKET pPacket)
1721 pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
1722 DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
1724 nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
1731 ==========================================================================
1733 Look up the MAC address in the MAC table. Return NULL if not found.
1735 pEntry - pointer to the MAC entry; NULL is not found
1736 ==========================================================================
1738 MAC_TABLE_ENTRY *MacTableLookup(
1739 IN PRTMP_ADAPTER pAd,
1743 MAC_TABLE_ENTRY *pEntry = NULL;
1745 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1746 pEntry = pAd->MacTab.Hash[HashIdx];
1748 while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh))
1750 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1755 pEntry = pEntry->pNext;
1761 MAC_TABLE_ENTRY *MacTableInsertEntry(
1762 IN PRTMP_ADAPTER pAd,
1765 IN BOOLEAN CleanAll)
1769 MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
1772 if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
1776 #ifdef CONFIG_STA_SUPPORT
1777 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1778 if (pAd->StaCfg.BssType == BSS_INFRA)
1780 #endif // CONFIG_STA_SUPPORT //
1782 // allocate one MAC entry
1783 NdisAcquireSpinLock(&pAd->MacTabLock);
1784 for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++) // skip entry#0 so that "entry index == AID" for fast lookup
1786 // pick up the first available vacancy
1787 if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
1788 (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
1789 (pAd->MacTab.Content[i].ValidAsApCli== FALSE) &&
1790 (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
1791 #ifdef CONFIG_STA_SUPPORT
1792 #ifdef QOS_DLS_SUPPORT
1793 && (pAd->MacTab.Content[i].ValidAsDls == FALSE)
1794 #endif // QOS_DLS_SUPPORT //
1795 #endif // CONFIG_STA_SUPPORT //
1798 pEntry = &pAd->MacTab.Content[i];
1799 if (CleanAll == TRUE)
1801 pEntry->MaxSupportedRate = RATE_11;
1802 pEntry->CurrTxRate = RATE_11;
1803 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1804 pEntry->PairwiseKey.KeyLen = 0;
1805 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1807 #ifdef CONFIG_STA_SUPPORT
1808 #ifdef QOS_DLS_SUPPORT
1809 if (apidx >= MIN_NET_DEVICE_FOR_DLS)
1811 pEntry->ValidAsCLI = FALSE;
1812 pEntry->ValidAsWDS = FALSE;
1813 pEntry->ValidAsApCli = FALSE;
1814 pEntry->ValidAsMesh = FALSE;
1815 pEntry->ValidAsDls = TRUE;
1816 pEntry->isCached = FALSE;
1819 #endif // QOS_DLS_SUPPORT //
1820 #endif // CONFIG_STA_SUPPORT //
1823 #ifdef CONFIG_STA_SUPPORT
1824 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1826 pEntry->ValidAsCLI = TRUE;
1827 pEntry->ValidAsWDS = FALSE;
1828 pEntry->ValidAsApCli = FALSE;
1829 pEntry->ValidAsMesh = FALSE;
1830 pEntry->ValidAsDls = FALSE;
1832 #endif // CONFIG_STA_SUPPORT //
1835 pEntry->bIAmBadAtheros = FALSE;
1837 pEntry->CMTimerRunning = FALSE;
1838 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
1839 pEntry->RSNIE_Len = 0;
1840 NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
1841 pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
1843 if (pEntry->ValidAsMesh)
1844 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH);
1845 else if (pEntry->ValidAsApCli)
1846 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI);
1847 else if (pEntry->ValidAsWDS)
1848 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS);
1849 #ifdef CONFIG_STA_SUPPORT
1850 #ifdef QOS_DLS_SUPPORT
1851 else if (pEntry->ValidAsDls)
1852 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_DLS);
1853 #endif // QOS_DLS_SUPPORT //
1854 #endif // CONFIG_STA_SUPPORT //
1856 pEntry->apidx = apidx;
1860 #ifdef CONFIG_STA_SUPPORT
1861 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1863 pEntry->AuthMode = pAd->StaCfg.AuthMode;
1864 pEntry->WepStatus = pAd->StaCfg.WepStatus;
1865 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
1867 #endif // CONFIG_STA_SUPPORT //
1870 pEntry->GTKState = REKEY_NEGOTIATING;
1871 pEntry->PairwiseKey.KeyLen = 0;
1872 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1873 #ifdef CONFIG_STA_SUPPORT
1874 #ifdef QOS_DLS_SUPPORT
1875 if (pEntry->ValidAsDls == TRUE)
1876 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
1877 #endif //QOS_DLS_SUPPORT
1878 #endif // CONFIG_STA_SUPPORT //
1879 pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
1880 pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
1881 COPY_MAC_ADDR(pEntry->Addr, pAddr);
1882 pEntry->Sst = SST_NOT_AUTH;
1883 pEntry->AuthState = AS_NOT_AUTH;
1884 pEntry->Aid = (USHORT)i; //0;
1885 pEntry->CapabilityInfo = 0;
1886 pEntry->PsMode = PWR_ACTIVE;
1887 pEntry->PsQIdleCount = 0;
1888 pEntry->NoDataIdleCount = 0;
1889 pEntry->ContinueTxFailCnt = 0;
1890 InitializeQueueHeader(&pEntry->PsQueue);
1893 pAd->MacTab.Size ++;
1894 // Add this entry into ASIC RX WCID search table
1895 RT28XX_STA_ENTRY_ADD(pAd, pEntry);
1897 DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size));
1902 // add this MAC entry into HASH table
1905 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1906 if (pAd->MacTab.Hash[HashIdx] == NULL)
1908 pAd->MacTab.Hash[HashIdx] = pEntry;
1912 pCurrEntry = pAd->MacTab.Hash[HashIdx];
1913 while (pCurrEntry->pNext != NULL)
1914 pCurrEntry = pCurrEntry->pNext;
1915 pCurrEntry->pNext = pEntry;
1919 NdisReleaseSpinLock(&pAd->MacTabLock);
1924 ==========================================================================
1926 Delete a specified client from MAC table
1927 ==========================================================================
1929 BOOLEAN MacTableDeleteEntry(
1930 IN PRTMP_ADAPTER pAd,
1935 MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
1937 //USHORT offset; // unused variable
1938 //UCHAR j; // unused variable
1940 if (wcid >= MAX_LEN_OF_MAC_TABLE)
1943 NdisAcquireSpinLock(&pAd->MacTabLock);
1945 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1946 //pEntry = pAd->MacTab.Hash[HashIdx];
1947 pEntry = &pAd->MacTab.Content[wcid];
1949 if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh
1950 #ifdef CONFIG_STA_SUPPORT
1951 #ifdef QOS_DLS_SUPPORT
1952 || pEntry->ValidAsDls
1953 #endif // QOS_DLS_SUPPORT //
1954 #endif // CONFIG_STA_SUPPORT //
1957 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1960 // Delete this entry from ASIC on-chip WCID Table
1961 RT28XX_STA_ENTRY_MAC_RESET(pAd, wcid);
1963 #ifdef DOT11_N_SUPPORT
1964 // free resources of BA
1965 BASessionTearDownALL(pAd, pEntry->Aid);
1966 #endif // DOT11_N_SUPPORT //
1970 pProbeEntry = pAd->MacTab.Hash[HashIdx];
1971 ASSERT(pProbeEntry);
1976 if (pProbeEntry == pEntry)
1978 if (pPrevEntry == NULL)
1980 pAd->MacTab.Hash[HashIdx] = pEntry->pNext;
1984 pPrevEntry->pNext = pEntry->pNext;
1989 pPrevEntry = pProbeEntry;
1990 pProbeEntry = pProbeEntry->pNext;
1991 } while (pProbeEntry);
1994 ASSERT(pProbeEntry != NULL);
1996 RT28XX_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
1999 if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
2001 RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
2002 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
2006 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
2007 pAd->MacTab.Size --;
2008 DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size));
2012 printk("\n%s: Impossible Wcid = %d !!!!!\n", __func__, wcid);
2016 NdisReleaseSpinLock(&pAd->MacTabLock);
2018 //Reset operating mode when no Sta.
2019 if (pAd->MacTab.Size == 0)
2021 #ifdef DOT11_N_SUPPORT
2022 pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
2023 #endif // DOT11_N_SUPPORT //
2024 AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/);
2032 ==========================================================================
2034 This routine reset the entire MAC table. All packets pending in
2035 the power-saving queues are freed here.
2036 ==========================================================================
2039 IN PRTMP_ADAPTER pAd)
2043 DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
2044 //NdisAcquireSpinLock(&pAd->MacTabLock);
2046 for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
2048 if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
2051 #ifdef DOT11_N_SUPPORT
2052 // free resources of BA
2053 BASessionTearDownALL(pAd, i);
2054 #endif // DOT11_N_SUPPORT //
2056 pAd->MacTab.Content[i].ValidAsCLI = FALSE;
2061 NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6);
2062 RT28XX_STA_ENTRY_MAC_RESET(pAd, i);
2065 //AsicDelWcidTab(pAd, i);
2073 ==========================================================================
2076 IRQL = DISPATCH_LEVEL
2078 ==========================================================================
2081 IN PRTMP_ADAPTER pAd,
2082 IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
2084 IN USHORT CapabilityInfo,
2086 IN USHORT ListenIntv)
2088 COPY_MAC_ADDR(AssocReq->Addr, pAddr);
2089 // Add mask to support 802.11b mode only
2090 AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request
2091 AssocReq->Timeout = Timeout;
2092 AssocReq->ListenIntv = ListenIntv;
2097 ==========================================================================
2100 IRQL = DISPATCH_LEVEL
2102 ==========================================================================
2104 VOID DisassocParmFill(
2105 IN PRTMP_ADAPTER pAd,
2106 IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
2110 COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
2111 DisassocReq->Reason = Reason;
2116 ========================================================================
2118 Routine Description:
2119 Check the out going frame, if this is an DHCP or ARP datagram
2120 will be duplicate another frame at low data rate transmit.
2123 pAd Pointer to our adapter
2124 pPacket Pointer to outgoing Ndis frame
2127 TRUE To be duplicate at Low data rate transmit. (1mb)
2130 IRQL = DISPATCH_LEVEL
2134 MAC header + IP Header + UDP Header
2138 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
2140 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
2143 port 0x43 means Bootstrap Protocol, server.
2144 Port 0x44 means Bootstrap Protocol, client.
2146 ========================================================================
2149 BOOLEAN RTMPCheckDHCPFrame(
2150 IN PRTMP_ADAPTER pAd,
2151 IN PNDIS_PACKET pPacket)
2153 PACKET_INFO PacketInfo;
2154 ULONG NumberOfBytesRead = 0;
2155 ULONG CurrentOffset = 0;
2156 PVOID pVirtualAddress = NULL;
2157 UINT NdisBufferLength;
2160 UCHAR ByteOffset36 = 0;
2161 UCHAR ByteOffset38 = 0;
2162 BOOLEAN ReadFirstParm = TRUE;
2164 RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength);
2166 NumberOfBytesRead += NdisBufferLength;
2167 pSrc = (PUCHAR) pVirtualAddress;
2168 Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
2171 // Check DHCP & BOOTP protocol
2173 while (NumberOfBytesRead <= PacketInfo.TotalPacketLength)
2175 if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE))
2177 CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength);
2178 ByteOffset36 = *(pSrc + CurrentOffset);
2179 ReadFirstParm = FALSE;
2182 if (NumberOfBytesRead >= 37)
2184 CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength);
2185 ByteOffset38 = *(pSrc + CurrentOffset);
2192 // Check for DHCP & BOOTP protocol
2193 if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43))
2196 // 2054 (hex 0806) for ARP datagrams
2197 // if this packet is not ARP datagrams, then do nothing
2198 // ARP datagrams will also be duplicate at 1mb broadcast frames
2200 if (Protocol != 0x0806 )
2208 BOOLEAN RTMPCheckEtherType(
2209 IN PRTMP_ADAPTER pAd,
2210 IN PNDIS_PACKET pPacket)
2216 UINT16 srcPort, dstPort;
2217 BOOLEAN status = TRUE;
2220 pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
2221 pktLen = GET_OS_PKT_LEN(pPacket);
2225 RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
2227 // get Ethernet protocol field
2228 TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13];
2230 pSrcBuf += LENGTH_802_3; // Skip the Ethernet Header.
2232 if (TypeLen <= 1500)
2233 { // 802.3, 802.3 LLC
2235 DestMAC(6) + SrcMAC(6) + Lenght(2) +
2236 DSAP(1) + SSAP(1) + Control(1) +
2237 if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
2238 => + SNAP (5, OriginationID(3) + etherType(2))
2240 if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03)
2242 Sniff2BytesFromNdisBuffer(pSrcBuf, 6, &Byte0, &Byte1);
2243 RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
2244 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2245 pSrcBuf += 8; // Skip this LLC/SNAP header
2249 //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.
2253 // If it's a VLAN packet, get the real Type/Length field.
2254 if (TypeLen == 0x8100)
2256 /* 0x8100 means VLAN packets */
2258 /* Dest. MAC Address (6-bytes) +
2259 Source MAC Address (6-bytes) +
2260 Length/Type = 802.1Q Tag Type (2-byte) +
2261 Tag Control Information (2-bytes) +
2262 Length / Type (2-bytes) +
2263 data payload (0-n bytes) +
2265 Frame Check Sequence (4-bytes) */
2267 RTMP_SET_PACKET_VLAN(pPacket, 1);
2268 Sniff2BytesFromNdisBuffer(pSrcBuf, 2, &Byte0, &Byte1);
2269 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2271 pSrcBuf += 4; // Skip the VLAN Header.
2278 ASSERT((pktLen > 34));
2279 if (*(pSrcBuf + 9) == 0x11)
2281 ASSERT((pktLen > 34)); // 14 for ethernet header, 20 for IP header
2283 pSrcBuf += 20; // Skip the IP header
2284 srcPort = OS_NTOHS(*((UINT16 *)pSrcBuf));
2285 dstPort = OS_NTOHS(*((UINT16 *)(pSrcBuf +2)));
2287 if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44))
2288 { //It's a BOOTP/DHCP packet
2289 RTMP_SET_PACKET_DHCP(pPacket, 1);
2297 RTMP_SET_PACKET_DHCP(pPacket, 1);
2303 RTMP_SET_PACKET_EAPOL(pPacket, 1);
2317 VOID Update_Rssi_Sample(
2318 IN PRTMP_ADAPTER pAd,
2319 IN RSSI_SAMPLE *pRssi,
2320 IN PRXWI_STRUC pRxWI)
2322 CHAR rssi0 = pRxWI->RSSI0;
2323 CHAR rssi1 = pRxWI->RSSI1;
2324 CHAR rssi2 = pRxWI->RSSI2;
2328 pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0);
2329 pRssi->AvgRssi0X8 = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
2330 pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
2335 pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1);
2336 pRssi->AvgRssi1X8 = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
2337 pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
2342 pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2);
2343 pRssi->AvgRssi2X8 = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
2344 pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
2350 // Normal legacy Rx packet indication
2351 VOID Indicate_Legacy_Packet(
2352 IN PRTMP_ADAPTER pAd,
2354 IN UCHAR FromWhichBSSID)
2356 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2357 UCHAR Header802_3[LENGTH_802_3];
2359 // 1. get 802.3 Header
2361 // a. pointer pRxBlk->pData to payload
2362 // b. modify pRxBlk->DataSize
2363 #ifdef CONFIG_STA_SUPPORT
2364 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2365 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2366 #endif // CONFIG_STA_SUPPORT //
2368 if (pRxBlk->DataSize > MAX_RX_PKT_LEN)
2370 #if 0 // sample take off, for multiple card design
2371 static int err_size;
2376 printk("Legacy DataSize = %d\n", pRxBlk->DataSize);
2377 hex_dump("802.3 Header", Header802_3, LENGTH_802_3);
2378 hex_dump("Payload", pRxBlk->pData, 64);
2384 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2389 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
2392 #ifdef DOT11_N_SUPPORT
2393 if (pAd->CommonCfg.bDisableReordering == 0)
2395 PBA_REC_ENTRY pBAEntry;
2397 UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID;
2398 UCHAR TID = pRxBlk->pRxWI->TID;
2401 #define REORDERING_PACKET_TIMEOUT ((100 * HZ)/1000) // system ticks -- 100 ms
2403 if (Wcid < MAX_LEN_OF_MAC_TABLE)
2405 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
2408 pBAEntry = &pAd->BATable.BARecEntry[Idx];
2409 // update last rx time
2410 NdisGetSystemUpTime(&Now32);
2411 if ((pBAEntry->list.qlen > 0) &&
2412 RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
2415 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);
2416 hex_dump("Dump the legacy Packet:", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), 64);
2417 ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
2422 #endif // DOT11_N_SUPPORT //
2425 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2428 // pass this 802.3 packet to upper layer or forward this packet to WM directly
2430 #ifdef CONFIG_STA_SUPPORT
2431 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2432 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
2433 #endif // CONFIG_STA_SUPPORT //
2438 // Normal, AMPDU or AMSDU
2439 VOID CmmRxnonRalinkFrameIndicate(
2440 IN PRTMP_ADAPTER pAd,
2442 IN UCHAR FromWhichBSSID)
2444 #ifdef DOT11_N_SUPPORT
2445 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
2447 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2450 #endif // DOT11_N_SUPPORT //
2452 #ifdef DOT11_N_SUPPORT
2453 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
2456 Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2459 #endif // DOT11_N_SUPPORT //
2461 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
2467 VOID CmmRxRalinkFrameIndicate(
2468 IN PRTMP_ADAPTER pAd,
2469 IN MAC_TABLE_ENTRY *pEntry,
2471 IN UCHAR FromWhichBSSID)
2473 UCHAR Header802_3[LENGTH_802_3];
2475 UINT16 Payload1Size, Payload2Size;
2477 PNDIS_PACKET pPacket2 = NULL;
2481 Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8);
2483 if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize))
2485 /* skip two byte MSDU2 len */
2487 pRxBlk->DataSize -= 2;
2492 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2496 // get 802.3 Header and remove LLC
2497 #ifdef CONFIG_STA_SUPPORT
2498 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2499 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2500 #endif // CONFIG_STA_SUPPORT //
2503 ASSERT(pRxBlk->pRxPacket);
2505 // Ralink Aggregation frame
2506 pAd->RalinkCounters.OneSecRxAggregationCount ++;
2507 Payload1Size = pRxBlk->DataSize - Msdu2Size;
2508 Payload2Size = Msdu2Size - LENGTH_802_3;
2510 pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
2511 #ifdef CONFIG_STA_SUPPORT
2512 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2513 pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID);
2514 #endif // CONFIG_STA_SUPPORT //
2519 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2523 // update payload size of 1st packet
2524 pRxBlk->DataSize = Payload1Size;
2525 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2527 #ifdef CONFIG_STA_SUPPORT
2528 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2529 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID);
2530 #endif // CONFIG_STA_SUPPORT //
2534 #ifdef CONFIG_STA_SUPPORT
2535 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2536 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
2537 #endif // CONFIG_STA_SUPPORT //
2542 #define RESET_FRAGFRAME(_fragFrame) \
2544 _fragFrame.RxSize = 0; \
2545 _fragFrame.Sequence = 0; \
2546 _fragFrame.LastFrag = 0; \
2547 _fragFrame.Flags = 0; \
2551 PNDIS_PACKET RTMPDeFragmentDataFrame(
2552 IN PRTMP_ADAPTER pAd,
2555 PHEADER_802_11 pHeader = pRxBlk->pHeader;
2556 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2557 UCHAR *pData = pRxBlk->pData;
2558 USHORT DataSize = pRxBlk->DataSize;
2559 PNDIS_PACKET pRetPacket = NULL;
2560 UCHAR *pFragBuffer = NULL;
2561 BOOLEAN bReassDone = FALSE;
2562 UCHAR HeaderRoom = 0;
2567 HeaderRoom = pData - (UCHAR *)pHeader;
2569 // Re-assemble the fragmented packets
2570 if (pHeader->Frag == 0) // Frag. Number is 0 : First frag or only one pkt
2572 // the first pkt of fragment, record it.
2573 if (pHeader->FC.MoreFrag)
2575 ASSERT(pAd->FragFrame.pFragPacket);
2576 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2577 pAd->FragFrame.RxSize = DataSize + HeaderRoom;
2578 NdisMoveMemory(pFragBuffer, pHeader, pAd->FragFrame.RxSize);
2579 pAd->FragFrame.Sequence = pHeader->Sequence;
2580 pAd->FragFrame.LastFrag = pHeader->Frag; // Should be 0
2581 ASSERT(pAd->FragFrame.LastFrag == 0);
2582 goto done; // end of processing this frame
2585 else //Middle & End of fragment
2587 if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
2588 (pHeader->Frag != (pAd->FragFrame.LastFrag + 1)))
2590 // Fragment is not the same sequence or out of fragment number order
2591 // Reset Fragment control blk
2592 RESET_FRAGFRAME(pAd->FragFrame);
2593 DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n"));
2594 goto done; // give up this frame
2596 else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE)
2598 // Fragment frame is too large, it exeeds the maximum frame size.
2599 // Reset Fragment control blk
2600 RESET_FRAGFRAME(pAd->FragFrame);
2601 DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
2602 goto done; // give up this frame
2606 // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.
2607 // In this case, we will dropt it.
2609 if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H)))
2611 DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag));
2612 goto done; // give up this frame
2615 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2617 // concatenate this fragment into the re-assembly buffer
2618 NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize);
2619 pAd->FragFrame.RxSize += DataSize;
2620 pAd->FragFrame.LastFrag = pHeader->Frag; // Update fragment number
2623 if (pHeader->FC.MoreFrag == FALSE)
2630 // always release rx fragmented packet
2631 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2633 // return defragmented packet if packet is reassembled completely
2634 // otherwise return NULL
2637 PNDIS_PACKET pNewFragPacket;
2639 // allocate a new packet buffer for fragment
2640 pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
2644 pRetPacket = pAd->FragFrame.pFragPacket;
2645 pAd->FragFrame.pFragPacket = pNewFragPacket;
2646 pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
2647 pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom;
2648 pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
2649 pRxBlk->pRxPacket = pRetPacket;
2653 RESET_FRAGFRAME(pAd->FragFrame);
2661 VOID Indicate_AMSDU_Packet(
2662 IN PRTMP_ADAPTER pAd,
2664 IN UCHAR FromWhichBSSID)
2668 update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
2669 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
2670 nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize);
2673 VOID Indicate_EAPOL_Packet(
2674 IN PRTMP_ADAPTER pAd,
2676 IN UCHAR FromWhichBSSID)
2678 MAC_TABLE_ENTRY *pEntry = NULL;
2681 #ifdef CONFIG_STA_SUPPORT
2682 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2684 pEntry = &pAd->MacTab.Content[BSSID_WCID];
2685 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
2688 #endif // CONFIG_STA_SUPPORT //
2692 DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
2694 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2699 #define BCN_TBTT_OFFSET 64 //defer 64 us
2700 VOID ReSyncBeaconTime(
2701 IN PRTMP_ADAPTER pAd)
2707 Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
2709 pAd->TbttTickCount++;
2712 // The updated BeaconInterval Value will affect Beacon Interval after two TBTT
2713 // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
2715 if (Offset == (BCN_TBTT_OFFSET-2))
2717 BCN_TIME_CFG_STRUC csr;
2718 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2719 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; // ASIC register in units of 1/16 TU = 64us
2720 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2724 if (Offset == (BCN_TBTT_OFFSET-1))
2726 BCN_TIME_CFG_STRUC csr;
2728 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2729 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU
2730 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);