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++;
715 BOOLEAN CanDoAggregateTransmit(
716 IN RTMP_ADAPTER *pAd,
717 IN NDIS_PACKET *pPacket,
721 //printk("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType);
723 if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
726 if (RTMP_GET_PACKET_DHCP(pPacket) ||
727 RTMP_GET_PACKET_EAPOL(pPacket) ||
728 RTMP_GET_PACKET_WAI(pPacket))
731 if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) &&
732 ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100)))
733 { // For AMSDU, allow the packets with total length < max-amsdu size
737 if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) &&
738 (pTxBlk->TxPacketList.Number == 2))
739 { // For RALINK-Aggregation, allow two frames in one batch.
743 #ifdef CONFIG_STA_SUPPORT
744 if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP
747 #endif // CONFIG_STA_SUPPORT //
754 ========================================================================
757 To do the enqueue operation and extract the first item of waiting
758 list. If a number of available shared memory segments could meet
759 the request of extracted item, the extracted item will be fragmented
760 into shared memory segments.
763 pAd Pointer to our adapter
764 pQueue Pointer to Waiting Queue
769 IRQL = DISPATCH_LEVEL
773 ========================================================================
775 VOID RTMPDeQueuePacket(
776 IN PRTMP_ADAPTER pAd,
777 IN BOOLEAN bIntContext,
778 IN UCHAR QIdx, /* BulkOutPipeId */
779 IN UCHAR Max_Tx_Packets)
781 PQUEUE_ENTRY pEntry = NULL;
782 PNDIS_PACKET pPacket;
783 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
785 PQUEUE_HEADER pQueue;
786 ULONG FreeNumber[NUM_OF_TX_RING];
787 UCHAR QueIdx, sQIdx, eQIdx;
788 unsigned long IrqFlags = 0;
789 BOOLEAN hasTxDesc = FALSE;
795 RtmpDiagStruct *pDiagStruct = &pAd->DiagStruct;
799 if (QIdx == NUM_OF_TX_RING)
802 eQIdx = 3; // 4 ACs, start from 0.
806 sQIdx = eQIdx = QIdx;
809 for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++)
813 RT28XX_START_DEQUEUE(pAd, QueIdx, IrqFlags);
816 firstRound = ((QueIdx == 0) ? TRUE : FALSE);
817 #endif // DBG_DIAGNOSE //
821 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |
822 fRTMP_ADAPTER_RADIO_OFF |
823 fRTMP_ADAPTER_RESET_IN_PROGRESS |
824 fRTMP_ADAPTER_HALT_IN_PROGRESS |
825 fRTMP_ADAPTER_NIC_NOT_EXIST))))
827 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
831 if (Count >= Max_Tx_Packets)
834 DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
835 if (&pAd->TxSwQueue[QueIdx] == NULL)
838 if (firstRound == TRUE)
839 pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][0]++;
840 #endif // DBG_DIAGNOSE //
841 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
846 // probe the Queue Head
847 pQueue = &pAd->TxSwQueue[QueIdx];
848 if ((pEntry = pQueue->Head) == NULL)
850 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
855 NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK));
856 //InitializeQueueHeader(&pTxBlk->TxPacketList); // Didn't need it because we already memzero it.
857 pTxBlk->QueIdx = QueIdx;
859 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
861 // Early check to make sure we have enoguh Tx Resource.
862 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
865 pAd->PrivateInfo.TxRingFullCnt++;
867 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
872 pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
873 pEntry = RemoveHeadQueue(pQueue);
874 pTxBlk->TotalFrameNum++;
875 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
876 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
877 pTxBlk->pPacket = pPacket;
878 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
880 if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME)
882 // Enhance SW Aggregation Mechanism
883 if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType))
885 InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
886 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
891 if((pEntry = pQueue->Head) == NULL)
894 // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation.
895 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
896 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
897 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
898 if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE))
901 //Remove the packet from the TxSwQueue and insert into pTxBlk
902 pEntry = RemoveHeadQueue(pQueue);
904 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
905 pTxBlk->TotalFrameNum++;
906 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
907 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
908 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
911 if (pTxBlk->TxPacketList.Number == 1)
912 pTxBlk->TxFrameType = TX_LEGACY_FRAME;
916 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
919 Count += pTxBlk->TxPacketList.Number;
921 // Do HardTransmit now.
922 #ifdef CONFIG_STA_SUPPORT
923 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
924 Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
925 #endif // CONFIG_STA_SUPPORT //
928 #if 0 // We should not break if HardTransmit failed. Well, at least now we should not!
929 if (Status != NDIS_STATUS_SUCCESS)
931 DBGPRINT(RT_DEBUG_TRACE /*RT_DEBUG_INFO*/,("RTMPHardTransmit return failed!!!\n"));
937 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
941 RTUSBKickBulkOut(pAd);
945 if ((pAd->blockQueueTab[QueIdx].SwTxQueueBlockFlag == TRUE)
946 && (pAd->TxSwQueue[QueIdx].Number < 1))
948 releaseNetIf(&pAd->blockQueueTab[QueIdx]);
950 #endif // BLOCK_NET_IF //
958 ========================================================================
961 Calculates the duration which is required to transmit out frames
962 with given size and specified rate.
965 pAd Pointer to our adapter
967 Size Frame size in units of byte
970 Duration number in units of usec
973 IRQL = DISPATCH_LEVEL
977 ========================================================================
979 USHORT RTMPCalcDuration(
980 IN PRTMP_ADAPTER pAd,
986 if (Rate < RATE_FIRST_OFDM_RATE) // CCK
988 if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED))
989 Duration = 96; // 72+24 preamble+plcp
991 Duration = 192; // 144+48 preamble+plcp
993 Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]);
994 if ((Size << 4) % RateIdTo500Kbps[Rate])
997 else if (Rate <= RATE_LAST_OFDM_RATE)// OFDM rates
999 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
1000 Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
1001 if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
1006 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
1009 return (USHORT)Duration;
1014 ========================================================================
1016 Routine Description:
1017 Calculates the duration which is required to transmit out frames
1018 with given size and specified rate.
1021 pTxWI Pointer to head of each MPDU to HW.
1022 Ack Setting for Ack requirement bit
1023 Fragment Setting for Fragment bit
1024 RetryMode Setting for retry mode
1025 Ifs Setting for IFS gap
1026 Rate Setting for transmit rate
1027 Service Setting for service
1029 TxPreamble Short or Long preamble when using CCK rates
1030 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1035 IRQL = PASSIVE_LEVEL
1036 IRQL = DISPATCH_LEVEL
1038 See also : BASmartHardTransmit() !!!
1040 ========================================================================
1043 IN PRTMP_ADAPTER pAd,
1044 IN PTXWI_STRUC pOutTxWI,
1047 IN BOOLEAN InsTimestamp,
1050 IN BOOLEAN NSeq, // HW new a sequence.
1059 IN HTTRANSMIT_SETTING *pTransmit)
1061 PMAC_TABLE_ENTRY pMac = NULL;
1065 if (WCID < MAX_LEN_OF_MAC_TABLE)
1066 pMac = &pAd->MacTab.Content[WCID];
1069 // Always use Long preamble before verifiation short preamble functionality works well.
1070 // Todo: remove the following line if short preamble functionality works
1072 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1073 NdisZeroMemory(&TxWI, TXWI_SIZE);
1078 pTxWI->CFACK = CFACK;
1079 pTxWI->TS= InsTimestamp;
1080 pTxWI->AMPDU = AMPDU;
1082 pTxWI->txop= Txopmode;
1085 // John tune the performace with Intel Client in 20 MHz performance
1086 #ifdef DOT11_N_SUPPORT
1087 BASize = pAd->CommonCfg.TxBASize;
1091 pTxWI->BAWinSize = BASize;
1092 pTxWI->ShortGI = pTransmit->field.ShortGI;
1093 pTxWI->STBC = pTransmit->field.STBC;
1094 #endif // DOT11_N_SUPPORT //
1096 pTxWI->WirelessCliID = WCID;
1097 pTxWI->MPDUtotalByteCount = Length;
1098 pTxWI->PacketId = PID;
1100 // If CCK or OFDM, BW must be 20
1101 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1102 #ifdef DOT11N_DRAFT3
1104 pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1105 #endif // DOT11N_DRAFT3 //
1107 pTxWI->MCS = pTransmit->field.MCS;
1108 pTxWI->PHYMODE = pTransmit->field.MODE;
1109 pTxWI->CFACK = CfAck;
1111 #ifdef DOT11_N_SUPPORT
1114 if (pAd->CommonCfg.bMIMOPSEnable)
1116 if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1118 // Dynamic MIMO Power Save Mode
1121 else if (pMac->MmpsMode == MMPS_STATIC)
1123 // Static MIMO Power Save Mode
1124 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1131 //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;
1132 if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled))
1134 pTxWI->MpduDensity = 7;
1138 pTxWI->MpduDensity = pMac->MpduDensity;
1141 #endif // DOT11_N_SUPPORT //
1143 pTxWI->PacketId = pTxWI->MCS;
1144 NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC));
1148 VOID RTMPWriteTxWI_Data(
1149 IN PRTMP_ADAPTER pAd,
1150 IN OUT PTXWI_STRUC pTxWI,
1153 HTTRANSMIT_SETTING *pTransmit;
1154 PMAC_TABLE_ENTRY pMacEntry;
1155 #ifdef DOT11_N_SUPPORT
1157 #endif // DOT11_N_SUPPORT //
1162 pTransmit = pTxBlk->pTransmit;
1163 pMacEntry = pTxBlk->pMacEntry;
1167 // Always use Long preamble before verifiation short preamble functionality works well.
1168 // Todo: remove the following line if short preamble functionality works
1170 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1171 NdisZeroMemory(pTxWI, TXWI_SIZE);
1173 pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1174 pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1175 pTxWI->txop = pTxBlk->FrameGap;
1177 #ifdef CONFIG_STA_SUPPORT
1178 #ifdef QOS_DLS_SUPPORT
1180 (pAd->StaCfg.BssType == BSS_INFRA) &&
1181 (pMacEntry->ValidAsDls == TRUE))
1182 pTxWI->WirelessCliID = BSSID_WCID;
1184 #endif // QOS_DLS_SUPPORT //
1185 #endif // CONFIG_STA_SUPPORT //
1186 pTxWI->WirelessCliID = pTxBlk->Wcid;
1188 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1189 pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
1191 // If CCK or OFDM, BW must be 20
1192 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1193 #ifdef DOT11_N_SUPPORT
1194 #ifdef DOT11N_DRAFT3
1196 pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1197 #endif // DOT11N_DRAFT3 //
1198 pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
1200 // John tune the performace with Intel Client in 20 MHz performance
1201 BASize = pAd->CommonCfg.TxBASize;
1202 if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry))
1204 UCHAR RABAOriIdx = 0; //The RA's BA Originator table index.
1206 RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
1207 BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1215 pTxWI->TxBF = pTransmit->field.TxBF;
1216 pTxWI->BAWinSize = BASize;
1217 pTxWI->ShortGI = pTransmit->field.ShortGI;
1218 pTxWI->STBC = pTransmit->field.STBC;
1219 #endif // DOT11_N_SUPPORT //
1221 pTxWI->MCS = pTransmit->field.MCS;
1222 pTxWI->PHYMODE = pTransmit->field.MODE;
1224 #ifdef DOT11_N_SUPPORT
1227 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1229 // Dynamic MIMO Power Save Mode
1232 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1234 // Static MIMO Power Save Mode
1235 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1242 if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled))
1244 pTxWI->MpduDensity = 7;
1248 pTxWI->MpduDensity = pMacEntry->MpduDensity;
1251 #endif // DOT11_N_SUPPORT //
1254 if (pTxBlk->QueIdx== 0)
1256 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1257 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1259 #endif // DBG_DIAGNOSE //
1261 // for rate adapation
1262 pTxWI->PacketId = pTxWI->MCS;
1266 VOID RTMPWriteTxWI_Cache(
1267 IN PRTMP_ADAPTER pAd,
1268 IN OUT PTXWI_STRUC pTxWI,
1271 PHTTRANSMIT_SETTING /*pTxHTPhyMode,*/ pTransmit;
1272 PMAC_TABLE_ENTRY pMacEntry;
1277 pMacEntry = pTxBlk->pMacEntry;
1278 pTransmit = pTxBlk->pTransmit;
1280 if (pMacEntry->bAutoTxRateSwitch)
1282 pTxWI->txop = IFS_HTTXOP;
1284 // If CCK or OFDM, BW must be 20
1285 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1286 pTxWI->ShortGI = pTransmit->field.ShortGI;
1287 pTxWI->STBC = pTransmit->field.STBC;
1289 pTxWI->MCS = pTransmit->field.MCS;
1290 pTxWI->PHYMODE = pTransmit->field.MODE;
1292 // set PID for TxRateSwitching
1293 pTxWI->PacketId = pTransmit->field.MCS;
1296 #ifdef DOT11_N_SUPPORT
1297 pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE);
1300 #ifdef DOT11N_DRAFT3
1302 pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1303 #endif // DOT11N_DRAFT3 //
1305 if (pAd->CommonCfg.bMIMOPSEnable)
1307 // MIMO Power Save Mode
1308 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1310 // Dynamic MIMO Power Save Mode
1313 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1315 // Static MIMO Power Save Mode
1316 if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7))
1323 #endif // DOT11_N_SUPPORT //
1326 if (pTxBlk->QueIdx== 0)
1328 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1329 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1331 #endif // DBG_DIAGNOSE //
1333 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1339 ========================================================================
1341 Routine Description:
1342 Calculates the duration which is required to transmit out frames
1343 with given size and specified rate.
1346 pTxD Pointer to transmit descriptor
1347 Ack Setting for Ack requirement bit
1348 Fragment Setting for Fragment bit
1349 RetryMode Setting for retry mode
1350 Ifs Setting for IFS gap
1351 Rate Setting for transmit rate
1352 Service Setting for service
1354 TxPreamble Short or Long preamble when using CCK rates
1355 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1360 IRQL = PASSIVE_LEVEL
1361 IRQL = DISPATCH_LEVEL
1363 ========================================================================
1365 VOID RTMPWriteTxDescriptor(
1366 IN PRTMP_ADAPTER pAd,
1372 // Always use Long preamble before verifiation short preamble functionality works well.
1373 // Todo: remove the following line if short preamble functionality works
1375 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1377 pTxD->WIV = (bWIV) ? 1: 0;
1378 pTxD->QSEL= (QueueSEL);
1379 //RT2860c?? fixed using EDCA queue for test... We doubt Queue1 has problem. 2006-09-26 Jan
1380 //pTxD->QSEL= FIFO_EDCA;
1381 if (pAd->bGenOneHCCA == TRUE)
1382 pTxD->QSEL= FIFO_HCCA;
1387 // should be called only when -
1388 // 1. MEADIA_CONNECTED
1389 // 2. AGGREGATION_IN_USED
1390 // 3. Fragmentation not in used
1391 // 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible
1392 BOOLEAN TxFrameIsAggregatible(
1393 IN PRTMP_ADAPTER pAd,
1394 IN PUCHAR pPrevAddr1,
1398 // can't aggregate EAPOL (802.1x) frame
1399 if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1402 // can't aggregate multicast/broadcast frame
1403 if (p8023hdr[0] & 0x01)
1406 if (INFRA_ON(pAd)) // must be unicast to AP
1408 else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA
1416 ========================================================================
1418 Routine Description:
1419 Check the MSDU Aggregation policy
1420 1.HT aggregation is A-MSDU
1421 2.legaacy rate aggregation is software aggregation by Ralink.
1429 ========================================================================
1431 BOOLEAN PeerIsAggreOn(
1432 IN PRTMP_ADAPTER pAd,
1434 IN PMAC_TABLE_ENTRY pMacEntry)
1436 ULONG AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
1438 if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags))
1440 #ifdef DOT11_N_SUPPORT
1441 if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX)
1445 #endif // DOT11_N_SUPPORT //
1447 #ifdef AGGREGATION_SUPPORT
1448 if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
1449 { // legacy Ralink Aggregation support
1452 #endif // AGGREGATION_SUPPORT //
1460 ========================================================================
1462 Routine Description:
1463 Check and fine the packet waiting in SW queue with highest priority
1466 pAd Pointer to our adapter
1469 pQueue Pointer to Waiting Queue
1471 IRQL = DISPATCH_LEVEL
1475 ========================================================================
1477 PQUEUE_HEADER RTMPCheckTxSwQueue(
1478 IN PRTMP_ADAPTER pAd,
1483 // 2004-11-15 to be removed. test aggregation only
1484 // if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2))
1487 Number = pAd->TxSwQueue[QID_AC_BK].Number
1488 + pAd->TxSwQueue[QID_AC_BE].Number
1489 + pAd->TxSwQueue[QID_AC_VI].Number
1490 + pAd->TxSwQueue[QID_AC_VO].Number
1491 + pAd->TxSwQueue[QID_HCCA].Number;
1493 if (pAd->TxSwQueue[QID_AC_VO].Head != NULL)
1495 *pQueIdx = QID_AC_VO;
1496 return (&pAd->TxSwQueue[QID_AC_VO]);
1498 else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL)
1500 *pQueIdx = QID_AC_VI;
1501 return (&pAd->TxSwQueue[QID_AC_VI]);
1503 else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL)
1505 *pQueIdx = QID_AC_BE;
1506 return (&pAd->TxSwQueue[QID_AC_BE]);
1508 else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL)
1510 *pQueIdx = QID_AC_BK;
1511 return (&pAd->TxSwQueue[QID_AC_BK]);
1513 else if (pAd->TxSwQueue[QID_HCCA].Head != NULL)
1515 *pQueIdx = QID_HCCA;
1516 return (&pAd->TxSwQueue[QID_HCCA]);
1519 // No packet pending in Tx Sw queue
1520 *pQueIdx = QID_AC_BK;
1528 ========================================================================
1530 Routine Description:
1531 Suspend MSDU transmission
1534 pAd Pointer to our adapter
1541 ========================================================================
1543 VOID RTMPSuspendMsduTransmission(
1544 IN PRTMP_ADAPTER pAd)
1546 DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n"));
1550 // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
1551 // use Lowbound as R66 value on ScanNextChannel(...)
1553 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue);
1555 // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)
1556 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd)));
1557 RTMPSetAGCInitValue(pAd, BW_20);
1559 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1560 //RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000); // abort all TX rings
1565 ========================================================================
1567 Routine Description:
1568 Resume MSDU transmission
1571 pAd Pointer to our adapter
1576 IRQL = DISPATCH_LEVEL
1580 ========================================================================
1582 VOID RTMPResumeMsduTransmission(
1583 IN PRTMP_ADAPTER pAd)
1587 DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
1590 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue);
1592 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1593 // sample, for IRQ LOCK to SEM LOCK
1594 // IrqState = pAd->irq_disabled;
1596 // RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1598 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1602 UINT deaggregate_AMSDU_announce(
1603 IN PRTMP_ADAPTER pAd,
1604 PNDIS_PACKET pPacket,
1609 USHORT SubFrameSize;
1610 PHEADER_802_3 pAMSDUsubheader;
1612 UCHAR Header802_3[14];
1614 PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP;
1615 PNDIS_PACKET pClonePacket;
1621 while (DataSize > LENGTH_802_3)
1626 //hex_dump("subheader", pData, 64);
1627 pAMSDUsubheader = (PHEADER_802_3)pData;
1628 //pData += LENGTH_802_3;
1629 PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8);
1630 SubFrameSize = PayloadSize + LENGTH_802_3;
1633 if ((DataSize < SubFrameSize) || (PayloadSize > 1518 ))
1638 //printk("%d subframe: Size = %d\n", nMSDU, PayloadSize);
1640 pPayload = pData + LENGTH_802_3;
1642 pSA = pData + MAC_ADDR_LEN;
1644 // convert to 802.3 header
1645 CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP);
1647 #ifdef CONFIG_STA_SUPPORT
1648 if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) )
1650 // avoid local heap overflow, use dyanamic allocation
1651 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
1652 memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize);
1653 Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize;
1654 WpaEAPOLKeyAction(pAd, Elem);
1657 #endif // CONFIG_STA_SUPPORT //
1659 #ifdef CONFIG_STA_SUPPORT
1660 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1662 if (pRemovedLLCSNAP)
1664 pPayload -= LENGTH_802_3;
1665 PayloadSize += LENGTH_802_3;
1666 NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3);
1669 #endif // CONFIG_STA_SUPPORT //
1671 pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
1674 #ifdef CONFIG_STA_SUPPORT
1675 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1676 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket));
1677 #endif // CONFIG_STA_SUPPORT //
1681 // A-MSDU has padding to multiple of 4 including subframe header.
1682 // align SubFrameSize up to multiple of 4
1683 SubFrameSize = (SubFrameSize+3)&(~0x3);
1686 if (SubFrameSize > 1528 || SubFrameSize < 32)
1691 if (DataSize > SubFrameSize)
1693 pData += SubFrameSize;
1694 DataSize -= SubFrameSize;
1703 // finally release original rx packet
1704 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1710 UINT BA_Reorder_AMSDU_Annnounce(
1711 IN PRTMP_ADAPTER pAd,
1712 IN PNDIS_PACKET pPacket)
1718 pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
1719 DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
1721 nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
1728 ==========================================================================
1730 Look up the MAC address in the MAC table. Return NULL if not found.
1732 pEntry - pointer to the MAC entry; NULL is not found
1733 ==========================================================================
1735 MAC_TABLE_ENTRY *MacTableLookup(
1736 IN PRTMP_ADAPTER pAd,
1740 MAC_TABLE_ENTRY *pEntry = NULL;
1742 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1743 pEntry = pAd->MacTab.Hash[HashIdx];
1745 while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh))
1747 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1752 pEntry = pEntry->pNext;
1758 MAC_TABLE_ENTRY *MacTableInsertEntry(
1759 IN PRTMP_ADAPTER pAd,
1762 IN BOOLEAN CleanAll)
1766 MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
1769 if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
1773 #ifdef CONFIG_STA_SUPPORT
1774 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1775 if (pAd->StaCfg.BssType == BSS_INFRA)
1777 #endif // CONFIG_STA_SUPPORT //
1779 // allocate one MAC entry
1780 NdisAcquireSpinLock(&pAd->MacTabLock);
1781 for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++) // skip entry#0 so that "entry index == AID" for fast lookup
1783 // pick up the first available vacancy
1784 if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
1785 (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
1786 (pAd->MacTab.Content[i].ValidAsApCli== FALSE) &&
1787 (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
1788 #ifdef CONFIG_STA_SUPPORT
1789 #ifdef QOS_DLS_SUPPORT
1790 && (pAd->MacTab.Content[i].ValidAsDls == FALSE)
1791 #endif // QOS_DLS_SUPPORT //
1792 #endif // CONFIG_STA_SUPPORT //
1795 pEntry = &pAd->MacTab.Content[i];
1796 if (CleanAll == TRUE)
1798 pEntry->MaxSupportedRate = RATE_11;
1799 pEntry->CurrTxRate = RATE_11;
1800 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1801 pEntry->PairwiseKey.KeyLen = 0;
1802 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1804 #ifdef CONFIG_STA_SUPPORT
1805 #ifdef QOS_DLS_SUPPORT
1806 if (apidx >= MIN_NET_DEVICE_FOR_DLS)
1808 pEntry->ValidAsCLI = FALSE;
1809 pEntry->ValidAsWDS = FALSE;
1810 pEntry->ValidAsApCli = FALSE;
1811 pEntry->ValidAsMesh = FALSE;
1812 pEntry->ValidAsDls = TRUE;
1813 pEntry->isCached = FALSE;
1816 #endif // QOS_DLS_SUPPORT //
1817 #endif // CONFIG_STA_SUPPORT //
1820 #ifdef CONFIG_STA_SUPPORT
1821 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1823 pEntry->ValidAsCLI = TRUE;
1824 pEntry->ValidAsWDS = FALSE;
1825 pEntry->ValidAsApCli = FALSE;
1826 pEntry->ValidAsMesh = FALSE;
1827 pEntry->ValidAsDls = FALSE;
1829 #endif // CONFIG_STA_SUPPORT //
1832 pEntry->bIAmBadAtheros = FALSE;
1834 pEntry->CMTimerRunning = FALSE;
1835 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
1836 pEntry->RSNIE_Len = 0;
1837 NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
1838 pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
1840 if (pEntry->ValidAsMesh)
1841 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH);
1842 else if (pEntry->ValidAsApCli)
1843 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI);
1844 else if (pEntry->ValidAsWDS)
1845 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS);
1846 #ifdef CONFIG_STA_SUPPORT
1847 #ifdef QOS_DLS_SUPPORT
1848 else if (pEntry->ValidAsDls)
1849 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_DLS);
1850 #endif // QOS_DLS_SUPPORT //
1851 #endif // CONFIG_STA_SUPPORT //
1853 pEntry->apidx = apidx;
1857 #ifdef CONFIG_STA_SUPPORT
1858 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1860 pEntry->AuthMode = pAd->StaCfg.AuthMode;
1861 pEntry->WepStatus = pAd->StaCfg.WepStatus;
1862 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
1864 #endif // CONFIG_STA_SUPPORT //
1867 pEntry->GTKState = REKEY_NEGOTIATING;
1868 pEntry->PairwiseKey.KeyLen = 0;
1869 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1870 #ifdef CONFIG_STA_SUPPORT
1871 #ifdef QOS_DLS_SUPPORT
1872 if (pEntry->ValidAsDls == TRUE)
1873 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
1874 #endif //QOS_DLS_SUPPORT
1875 #endif // CONFIG_STA_SUPPORT //
1876 pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
1877 pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
1878 COPY_MAC_ADDR(pEntry->Addr, pAddr);
1879 pEntry->Sst = SST_NOT_AUTH;
1880 pEntry->AuthState = AS_NOT_AUTH;
1881 pEntry->Aid = (USHORT)i; //0;
1882 pEntry->CapabilityInfo = 0;
1883 pEntry->PsMode = PWR_ACTIVE;
1884 pEntry->PsQIdleCount = 0;
1885 pEntry->NoDataIdleCount = 0;
1886 pEntry->ContinueTxFailCnt = 0;
1887 InitializeQueueHeader(&pEntry->PsQueue);
1890 pAd->MacTab.Size ++;
1891 // Add this entry into ASIC RX WCID search table
1892 RT28XX_STA_ENTRY_ADD(pAd, pEntry);
1894 DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size));
1899 // add this MAC entry into HASH table
1902 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1903 if (pAd->MacTab.Hash[HashIdx] == NULL)
1905 pAd->MacTab.Hash[HashIdx] = pEntry;
1909 pCurrEntry = pAd->MacTab.Hash[HashIdx];
1910 while (pCurrEntry->pNext != NULL)
1911 pCurrEntry = pCurrEntry->pNext;
1912 pCurrEntry->pNext = pEntry;
1916 NdisReleaseSpinLock(&pAd->MacTabLock);
1921 ==========================================================================
1923 Delete a specified client from MAC table
1924 ==========================================================================
1926 BOOLEAN MacTableDeleteEntry(
1927 IN PRTMP_ADAPTER pAd,
1932 MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
1934 //USHORT offset; // unused variable
1935 //UCHAR j; // unused variable
1937 if (wcid >= MAX_LEN_OF_MAC_TABLE)
1940 NdisAcquireSpinLock(&pAd->MacTabLock);
1942 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1943 //pEntry = pAd->MacTab.Hash[HashIdx];
1944 pEntry = &pAd->MacTab.Content[wcid];
1946 if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh
1947 #ifdef CONFIG_STA_SUPPORT
1948 #ifdef QOS_DLS_SUPPORT
1949 || pEntry->ValidAsDls
1950 #endif // QOS_DLS_SUPPORT //
1951 #endif // CONFIG_STA_SUPPORT //
1954 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1957 // Delete this entry from ASIC on-chip WCID Table
1958 RT28XX_STA_ENTRY_MAC_RESET(pAd, wcid);
1960 #ifdef DOT11_N_SUPPORT
1961 // free resources of BA
1962 BASessionTearDownALL(pAd, pEntry->Aid);
1963 #endif // DOT11_N_SUPPORT //
1967 pProbeEntry = pAd->MacTab.Hash[HashIdx];
1968 ASSERT(pProbeEntry);
1973 if (pProbeEntry == pEntry)
1975 if (pPrevEntry == NULL)
1977 pAd->MacTab.Hash[HashIdx] = pEntry->pNext;
1981 pPrevEntry->pNext = pEntry->pNext;
1986 pPrevEntry = pProbeEntry;
1987 pProbeEntry = pProbeEntry->pNext;
1988 } while (pProbeEntry);
1991 ASSERT(pProbeEntry != NULL);
1993 RT28XX_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
1996 if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
1998 RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
1999 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
2003 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
2004 pAd->MacTab.Size --;
2005 DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size));
2009 printk("\n%s: Impossible Wcid = %d !!!!!\n", __func__, wcid);
2013 NdisReleaseSpinLock(&pAd->MacTabLock);
2015 //Reset operating mode when no Sta.
2016 if (pAd->MacTab.Size == 0)
2018 #ifdef DOT11_N_SUPPORT
2019 pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
2020 #endif // DOT11_N_SUPPORT //
2021 AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/);
2029 ==========================================================================
2031 This routine reset the entire MAC table. All packets pending in
2032 the power-saving queues are freed here.
2033 ==========================================================================
2036 IN PRTMP_ADAPTER pAd)
2040 DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
2041 //NdisAcquireSpinLock(&pAd->MacTabLock);
2043 for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
2045 if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
2048 #ifdef DOT11_N_SUPPORT
2049 // free resources of BA
2050 BASessionTearDownALL(pAd, i);
2051 #endif // DOT11_N_SUPPORT //
2053 pAd->MacTab.Content[i].ValidAsCLI = FALSE;
2058 NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6);
2059 RT28XX_STA_ENTRY_MAC_RESET(pAd, i);
2062 //AsicDelWcidTab(pAd, i);
2070 ==========================================================================
2073 IRQL = DISPATCH_LEVEL
2075 ==========================================================================
2078 IN PRTMP_ADAPTER pAd,
2079 IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
2081 IN USHORT CapabilityInfo,
2083 IN USHORT ListenIntv)
2085 COPY_MAC_ADDR(AssocReq->Addr, pAddr);
2086 // Add mask to support 802.11b mode only
2087 AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request
2088 AssocReq->Timeout = Timeout;
2089 AssocReq->ListenIntv = ListenIntv;
2094 ==========================================================================
2097 IRQL = DISPATCH_LEVEL
2099 ==========================================================================
2101 VOID DisassocParmFill(
2102 IN PRTMP_ADAPTER pAd,
2103 IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
2107 COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
2108 DisassocReq->Reason = Reason;
2113 ========================================================================
2115 Routine Description:
2116 Check the out going frame, if this is an DHCP or ARP datagram
2117 will be duplicate another frame at low data rate transmit.
2120 pAd Pointer to our adapter
2121 pPacket Pointer to outgoing Ndis frame
2124 TRUE To be duplicate at Low data rate transmit. (1mb)
2127 IRQL = DISPATCH_LEVEL
2131 MAC header + IP Header + UDP Header
2135 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
2137 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
2140 port 0x43 means Bootstrap Protocol, server.
2141 Port 0x44 means Bootstrap Protocol, client.
2143 ========================================================================
2146 BOOLEAN RTMPCheckDHCPFrame(
2147 IN PRTMP_ADAPTER pAd,
2148 IN PNDIS_PACKET pPacket)
2150 PACKET_INFO PacketInfo;
2151 ULONG NumberOfBytesRead = 0;
2152 ULONG CurrentOffset = 0;
2153 PVOID pVirtualAddress = NULL;
2154 UINT NdisBufferLength;
2157 UCHAR ByteOffset36 = 0;
2158 UCHAR ByteOffset38 = 0;
2159 BOOLEAN ReadFirstParm = TRUE;
2161 RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength);
2163 NumberOfBytesRead += NdisBufferLength;
2164 pSrc = (PUCHAR) pVirtualAddress;
2165 Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
2168 // Check DHCP & BOOTP protocol
2170 while (NumberOfBytesRead <= PacketInfo.TotalPacketLength)
2172 if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE))
2174 CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength);
2175 ByteOffset36 = *(pSrc + CurrentOffset);
2176 ReadFirstParm = FALSE;
2179 if (NumberOfBytesRead >= 37)
2181 CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength);
2182 ByteOffset38 = *(pSrc + CurrentOffset);
2189 // Check for DHCP & BOOTP protocol
2190 if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43))
2193 // 2054 (hex 0806) for ARP datagrams
2194 // if this packet is not ARP datagrams, then do nothing
2195 // ARP datagrams will also be duplicate at 1mb broadcast frames
2197 if (Protocol != 0x0806 )
2205 BOOLEAN RTMPCheckEtherType(
2206 IN PRTMP_ADAPTER pAd,
2207 IN PNDIS_PACKET pPacket)
2213 UINT16 srcPort, dstPort;
2214 BOOLEAN status = TRUE;
2217 pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
2218 pktLen = GET_OS_PKT_LEN(pPacket);
2222 RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
2224 // get Ethernet protocol field
2225 TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13];
2227 pSrcBuf += LENGTH_802_3; // Skip the Ethernet Header.
2229 if (TypeLen <= 1500)
2230 { // 802.3, 802.3 LLC
2232 DestMAC(6) + SrcMAC(6) + Lenght(2) +
2233 DSAP(1) + SSAP(1) + Control(1) +
2234 if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
2235 => + SNAP (5, OriginationID(3) + etherType(2))
2237 if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03)
2239 Sniff2BytesFromNdisBuffer(pSrcBuf, 6, &Byte0, &Byte1);
2240 RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
2241 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2242 pSrcBuf += 8; // Skip this LLC/SNAP header
2246 //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.
2250 // If it's a VLAN packet, get the real Type/Length field.
2251 if (TypeLen == 0x8100)
2253 /* 0x8100 means VLAN packets */
2255 /* Dest. MAC Address (6-bytes) +
2256 Source MAC Address (6-bytes) +
2257 Length/Type = 802.1Q Tag Type (2-byte) +
2258 Tag Control Information (2-bytes) +
2259 Length / Type (2-bytes) +
2260 data payload (0-n bytes) +
2262 Frame Check Sequence (4-bytes) */
2264 RTMP_SET_PACKET_VLAN(pPacket, 1);
2265 Sniff2BytesFromNdisBuffer(pSrcBuf, 2, &Byte0, &Byte1);
2266 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2268 pSrcBuf += 4; // Skip the VLAN Header.
2275 ASSERT((pktLen > 34));
2276 if (*(pSrcBuf + 9) == 0x11)
2278 ASSERT((pktLen > 34)); // 14 for ethernet header, 20 for IP header
2280 pSrcBuf += 20; // Skip the IP header
2281 srcPort = OS_NTOHS(*((UINT16 *)pSrcBuf));
2282 dstPort = OS_NTOHS(*((UINT16 *)(pSrcBuf +2)));
2284 if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44))
2285 { //It's a BOOTP/DHCP packet
2286 RTMP_SET_PACKET_DHCP(pPacket, 1);
2294 RTMP_SET_PACKET_DHCP(pPacket, 1);
2300 RTMP_SET_PACKET_EAPOL(pPacket, 1);
2314 VOID Update_Rssi_Sample(
2315 IN PRTMP_ADAPTER pAd,
2316 IN RSSI_SAMPLE *pRssi,
2317 IN PRXWI_STRUC pRxWI)
2319 CHAR rssi0 = pRxWI->RSSI0;
2320 CHAR rssi1 = pRxWI->RSSI1;
2321 CHAR rssi2 = pRxWI->RSSI2;
2325 pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0);
2326 pRssi->AvgRssi0X8 = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
2327 pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
2332 pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1);
2333 pRssi->AvgRssi1X8 = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
2334 pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
2339 pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2);
2340 pRssi->AvgRssi2X8 = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
2341 pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
2347 // Normal legacy Rx packet indication
2348 VOID Indicate_Legacy_Packet(
2349 IN PRTMP_ADAPTER pAd,
2351 IN UCHAR FromWhichBSSID)
2353 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2354 UCHAR Header802_3[LENGTH_802_3];
2356 // 1. get 802.3 Header
2358 // a. pointer pRxBlk->pData to payload
2359 // b. modify pRxBlk->DataSize
2360 #ifdef CONFIG_STA_SUPPORT
2361 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2362 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2363 #endif // CONFIG_STA_SUPPORT //
2365 if (pRxBlk->DataSize > MAX_RX_PKT_LEN)
2367 #if 0 // sample take off, for multiple card design
2368 static int err_size;
2373 printk("Legacy DataSize = %d\n", pRxBlk->DataSize);
2374 hex_dump("802.3 Header", Header802_3, LENGTH_802_3);
2375 hex_dump("Payload", pRxBlk->pData, 64);
2381 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2386 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
2389 #ifdef DOT11_N_SUPPORT
2390 if (pAd->CommonCfg.bDisableReordering == 0)
2392 PBA_REC_ENTRY pBAEntry;
2394 UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID;
2395 UCHAR TID = pRxBlk->pRxWI->TID;
2398 #define REORDERING_PACKET_TIMEOUT ((100 * HZ)/1000) // system ticks -- 100 ms
2400 if (Wcid < MAX_LEN_OF_MAC_TABLE)
2402 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
2405 pBAEntry = &pAd->BATable.BARecEntry[Idx];
2406 // update last rx time
2407 NdisGetSystemUpTime(&Now32);
2408 if ((pBAEntry->list.qlen > 0) &&
2409 RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
2412 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);
2413 hex_dump("Dump the legacy Packet:", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), 64);
2414 ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
2419 #endif // DOT11_N_SUPPORT //
2422 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2425 // pass this 802.3 packet to upper layer or forward this packet to WM directly
2427 #ifdef CONFIG_STA_SUPPORT
2428 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2429 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
2430 #endif // CONFIG_STA_SUPPORT //
2435 // Normal, AMPDU or AMSDU
2436 VOID CmmRxnonRalinkFrameIndicate(
2437 IN PRTMP_ADAPTER pAd,
2439 IN UCHAR FromWhichBSSID)
2441 #ifdef DOT11_N_SUPPORT
2442 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
2444 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2447 #endif // DOT11_N_SUPPORT //
2449 #ifdef DOT11_N_SUPPORT
2450 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
2453 Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2456 #endif // DOT11_N_SUPPORT //
2458 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
2464 VOID CmmRxRalinkFrameIndicate(
2465 IN PRTMP_ADAPTER pAd,
2466 IN MAC_TABLE_ENTRY *pEntry,
2468 IN UCHAR FromWhichBSSID)
2470 UCHAR Header802_3[LENGTH_802_3];
2472 UINT16 Payload1Size, Payload2Size;
2474 PNDIS_PACKET pPacket2 = NULL;
2478 Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8);
2480 if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize))
2482 /* skip two byte MSDU2 len */
2484 pRxBlk->DataSize -= 2;
2489 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2493 // get 802.3 Header and remove LLC
2494 #ifdef CONFIG_STA_SUPPORT
2495 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2496 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2497 #endif // CONFIG_STA_SUPPORT //
2500 ASSERT(pRxBlk->pRxPacket);
2502 // Ralink Aggregation frame
2503 pAd->RalinkCounters.OneSecRxAggregationCount ++;
2504 Payload1Size = pRxBlk->DataSize - Msdu2Size;
2505 Payload2Size = Msdu2Size - LENGTH_802_3;
2507 pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
2508 #ifdef CONFIG_STA_SUPPORT
2509 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2510 pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID);
2511 #endif // CONFIG_STA_SUPPORT //
2516 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2520 // update payload size of 1st packet
2521 pRxBlk->DataSize = Payload1Size;
2522 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2524 #ifdef CONFIG_STA_SUPPORT
2525 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2526 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID);
2527 #endif // CONFIG_STA_SUPPORT //
2531 #ifdef CONFIG_STA_SUPPORT
2532 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2533 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
2534 #endif // CONFIG_STA_SUPPORT //
2539 #define RESET_FRAGFRAME(_fragFrame) \
2541 _fragFrame.RxSize = 0; \
2542 _fragFrame.Sequence = 0; \
2543 _fragFrame.LastFrag = 0; \
2544 _fragFrame.Flags = 0; \
2548 PNDIS_PACKET RTMPDeFragmentDataFrame(
2549 IN PRTMP_ADAPTER pAd,
2552 PHEADER_802_11 pHeader = pRxBlk->pHeader;
2553 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2554 UCHAR *pData = pRxBlk->pData;
2555 USHORT DataSize = pRxBlk->DataSize;
2556 PNDIS_PACKET pRetPacket = NULL;
2557 UCHAR *pFragBuffer = NULL;
2558 BOOLEAN bReassDone = FALSE;
2559 UCHAR HeaderRoom = 0;
2564 HeaderRoom = pData - (UCHAR *)pHeader;
2566 // Re-assemble the fragmented packets
2567 if (pHeader->Frag == 0) // Frag. Number is 0 : First frag or only one pkt
2569 // the first pkt of fragment, record it.
2570 if (pHeader->FC.MoreFrag)
2572 ASSERT(pAd->FragFrame.pFragPacket);
2573 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2574 pAd->FragFrame.RxSize = DataSize + HeaderRoom;
2575 NdisMoveMemory(pFragBuffer, pHeader, pAd->FragFrame.RxSize);
2576 pAd->FragFrame.Sequence = pHeader->Sequence;
2577 pAd->FragFrame.LastFrag = pHeader->Frag; // Should be 0
2578 ASSERT(pAd->FragFrame.LastFrag == 0);
2579 goto done; // end of processing this frame
2582 else //Middle & End of fragment
2584 if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
2585 (pHeader->Frag != (pAd->FragFrame.LastFrag + 1)))
2587 // Fragment is not the same sequence or out of fragment number order
2588 // Reset Fragment control blk
2589 RESET_FRAGFRAME(pAd->FragFrame);
2590 DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n"));
2591 goto done; // give up this frame
2593 else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE)
2595 // Fragment frame is too large, it exeeds the maximum frame size.
2596 // Reset Fragment control blk
2597 RESET_FRAGFRAME(pAd->FragFrame);
2598 DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
2599 goto done; // give up this frame
2603 // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.
2604 // In this case, we will dropt it.
2606 if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H)))
2608 DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag));
2609 goto done; // give up this frame
2612 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2614 // concatenate this fragment into the re-assembly buffer
2615 NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize);
2616 pAd->FragFrame.RxSize += DataSize;
2617 pAd->FragFrame.LastFrag = pHeader->Frag; // Update fragment number
2620 if (pHeader->FC.MoreFrag == FALSE)
2627 // always release rx fragmented packet
2628 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2630 // return defragmented packet if packet is reassembled completely
2631 // otherwise return NULL
2634 PNDIS_PACKET pNewFragPacket;
2636 // allocate a new packet buffer for fragment
2637 pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
2641 pRetPacket = pAd->FragFrame.pFragPacket;
2642 pAd->FragFrame.pFragPacket = pNewFragPacket;
2643 pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
2644 pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom;
2645 pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
2646 pRxBlk->pRxPacket = pRetPacket;
2650 RESET_FRAGFRAME(pAd->FragFrame);
2658 VOID Indicate_AMSDU_Packet(
2659 IN PRTMP_ADAPTER pAd,
2661 IN UCHAR FromWhichBSSID)
2665 update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
2666 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
2667 nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize);
2670 VOID Indicate_EAPOL_Packet(
2671 IN PRTMP_ADAPTER pAd,
2673 IN UCHAR FromWhichBSSID)
2675 MAC_TABLE_ENTRY *pEntry = NULL;
2678 #ifdef CONFIG_STA_SUPPORT
2679 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2681 pEntry = &pAd->MacTab.Content[BSSID_WCID];
2682 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
2685 #endif // CONFIG_STA_SUPPORT //
2689 DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
2691 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2696 #define BCN_TBTT_OFFSET 64 //defer 64 us
2697 VOID ReSyncBeaconTime(
2698 IN PRTMP_ADAPTER pAd)
2704 Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
2706 pAd->TbttTickCount++;
2709 // The updated BeaconInterval Value will affect Beacon Interval after two TBTT
2710 // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
2712 if (Offset == (BCN_TBTT_OFFSET-2))
2714 BCN_TIME_CFG_STRUC csr;
2715 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2716 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; // ASIC register in units of 1/16 TU = 64us
2717 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2721 if (Offset == (BCN_TBTT_OFFSET-1))
2723 BCN_TIME_CFG_STRUC csr;
2725 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2726 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU
2727 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);