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 *************************************************************************
29 #include "../rt_config.h"
32 UCHAR SNAP_802_1H[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
33 UCHAR SNAP_BRIDGE_TUNNEL[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8};
34 // Add Cisco Aironet SNAP heade for CCX2 support
35 UCHAR SNAP_AIRONET[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00};
36 UCHAR CKIP_LLC_SNAP[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02};
37 UCHAR EAPOL_LLC_SNAP[]= {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e};
38 UCHAR EAPOL[] = {0x88, 0x8e};
39 UCHAR TPID[] = {0x81, 0x00}; /* VLAN related */
41 UCHAR IPX[] = {0x81, 0x37};
42 UCHAR APPLE_TALK[] = {0x80, 0xf3};
43 UCHAR RateIdToPlcpSignal[12] = {
44 0, /* RATE_1 */ 1, /* RATE_2 */ 2, /* RATE_5_5 */ 3, /* RATE_11 */ // see BBP spec
45 11, /* RATE_6 */ 15, /* RATE_9 */ 10, /* RATE_12 */ 14, /* RATE_18 */ // see IEEE802.11a-1999 p.14
46 9, /* RATE_24 */ 13, /* RATE_36 */ 8, /* RATE_48 */ 12 /* RATE_54 */ }; // see IEEE802.11a-1999 p.14
48 UCHAR OfdmSignalToRateId[16] = {
49 RATE_54, RATE_54, RATE_54, RATE_54, // OFDM PLCP Signal = 0, 1, 2, 3 respectively
50 RATE_54, RATE_54, RATE_54, RATE_54, // OFDM PLCP Signal = 4, 5, 6, 7 respectively
51 RATE_48, RATE_24, RATE_12, RATE_6, // OFDM PLCP Signal = 8, 9, 10, 11 respectively
52 RATE_54, RATE_36, RATE_18, RATE_9, // OFDM PLCP Signal = 12, 13, 14, 15 respectively
55 UCHAR OfdmRateToRxwiMCS[12] = {
57 0, 1, 2, 3, // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3
58 4, 5, 6, 7, // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7
60 UCHAR RxwiMCSToOfdmRate[12] = {
61 RATE_6, RATE_9, RATE_12, RATE_18,
62 RATE_24, RATE_36, RATE_48, RATE_54, // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3
63 4, 5, 6, 7, // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7
66 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"};
68 UCHAR default_cwmin[]={CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1, CW_MIN_IN_BITS-2};
69 //UCHAR default_cwmax[]={CW_MAX_IN_BITS, CW_MAX_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1};
70 UCHAR default_sta_aifsn[]={3,7,2,2};
72 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};
76 ========================================================================
79 API for MLME to transmit management frame to AP (BSS Mode)
80 or station (IBSS Mode)
83 pAd Pointer to our adapter
84 pData Pointer to the outgoing 802.11 frame
85 Length Size of outgoing management frame
97 ========================================================================
99 NDIS_STATUS MiniportMMRequest(
100 IN PRTMP_ADAPTER pAd,
105 PNDIS_PACKET pPacket;
106 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
108 UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN];
110 unsigned long IrqFlags = 0;
112 #endif // RTMP_MAC_PCI //
113 BOOLEAN bUseDataQ = FALSE;
116 ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
118 if ((QueIdx & MGMT_USE_QUEUE_FLAG) == MGMT_USE_QUEUE_FLAG)
121 QueIdx &= (~MGMT_USE_QUEUE_FLAG);
126 IrqState = pAd->irq_disabled;
127 if (pAd->MACVersion == 0x28600100)
129 QueIdx = (bUseDataQ ==TRUE ? QueIdx : 3);
132 if (bUseDataQ && (!IrqState))
133 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
134 #endif // RTMP_MAC_PCI //
138 // Reset is in progress, stop immediately
139 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
140 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)||
141 !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
143 Status = NDIS_STATUS_FAILURE;
147 // Check Free priority queue
148 // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing.
152 retryCnt = MAX_DATAMM_RETRY;
153 // free Tx(QueIdx) resources
154 RTMPFreeTXDUponTxDmaDone(pAd, QueIdx);
155 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
158 #endif // RTMP_MAC_PCI //
160 FreeNum = GET_MGMTRING_FREENO(pAd);
165 // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870
166 NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE));
167 Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE), pData, Length);
168 if (Status != NDIS_STATUS_SUCCESS)
170 DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
174 //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
175 //pAd->CommonCfg.MlmeRate = RATE_2;
181 Status = MlmeDataHardTransmit(pAd, QueIdx, pPacket);
185 #endif // RTMP_MAC_PCI //
186 Status = MlmeHardTransmit(pAd, QueIdx, pPacket);
187 if (Status == NDIS_STATUS_SUCCESS)
190 RTMPFreeNdisPacket(pAd, pPacket);
194 pAd->RalinkCounters.MgmtRingFullCount++;
199 DBGPRINT(RT_DEBUG_TRACE, ("retryCnt %d\n", retryCnt));
202 DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in DataRing, MgmtRingFullCount=%ld!\n",
203 QueIdx, pAd->RalinkCounters.MgmtRingFullCount));
206 #endif // RTMP_MAC_PCI //
207 DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n",
208 QueIdx, pAd->RalinkCounters.MgmtRingFullCount));
210 } while (retryCnt > 0);
214 if (bUseDataQ && (!IrqState))
215 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
216 #endif // RTMP_MAC_PCI //
225 ========================================================================
228 Copy frame from waiting queue into relative ring buffer and set
229 appropriate ASIC register to kick hardware transmit function
232 pAd Pointer to our adapter
233 pBuffer Pointer to memory of outgoing frame
234 Length Size of outgoing management frame
242 IRQL = DISPATCH_LEVEL
246 ========================================================================
248 NDIS_STATUS MlmeHardTransmit(
249 IN PRTMP_ADAPTER pAd,
251 IN PNDIS_PACKET pPacket)
253 PACKET_INFO PacketInfo;
256 PHEADER_802_11 pHeader_802_11;
258 if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
261 return NDIS_STATUS_FAILURE;
264 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
265 if (pSrcBufVA == NULL)
266 return NDIS_STATUS_FAILURE;
268 pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE);
272 if ( pAd->MACVersion == 0x28600100 )
273 return MlmeHardTransmitTxRing(pAd,QueIdx,pPacket);
275 #endif // RTMP_MAC_PCI //
276 return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
281 NDIS_STATUS MlmeHardTransmitMgmtRing(
282 IN PRTMP_ADAPTER pAd,
284 IN PNDIS_PACKET pPacket)
286 PACKET_INFO PacketInfo;
289 PHEADER_802_11 pHeader_802_11;
290 BOOLEAN bAckRequired, bInsertTimestamp;
292 PTXWI_STRUC pFirstTxWI;
293 MAC_TABLE_ENTRY *pMacEntry = NULL;
296 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
298 // Make sure MGMT ring resource won't be used by other threads
299 RTMP_SEM_LOCK(&pAd->MgmtRingLock);
300 if (pSrcBufVA == NULL)
302 // The buffer shouldn't be NULL
303 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
304 return NDIS_STATUS_FAILURE;
308 // outgoing frame always wakeup PHY to prevent frame lost
309 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
310 AsicForceWakeup(pAd, TRUE);
313 pFirstTxWI = (PTXWI_STRUC)(pSrcBufVA + TXINFO_SIZE);
314 pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); //TXWI_SIZE);
316 if (pHeader_802_11->Addr1[0] & 0x01)
318 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
322 MlmeRate = pAd->CommonCfg.MlmeRate;
325 // Verify Mlme rate for a / g bands.
326 if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
329 if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
330 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
332 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
336 // Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode.
337 if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED
338 || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED
341 if (pAd->LatchRfRegs.Channel > 14)
342 pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
344 pAd->CommonCfg.MlmeTransmit.field.MODE = 0;
349 // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
350 // Snice it's been set to 0 while on MgtMacHeaderInit
351 // By the way this will cause frame to be send on PWR_SAVE failed.
353 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE; // (pAd->StaCfg.Psm == PWR_SAVE);
356 // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
357 // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
358 // if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL))
360 if ((pHeader_802_11->FC.SubType == SUBTYPE_ACTION) ||
361 ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
362 ((pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL) ||
363 (pHeader_802_11->FC.SubType == SUBTYPE_NULL_FUNC))))
365 if (pAd->StaCfg.Psm == PWR_SAVE)
366 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
368 pHeader_802_11->FC.PwrMgmt = pAd->CommonCfg.bAPSDForcePowerSave;
376 bInsertTimestamp = FALSE;
377 if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
379 //Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue.
380 if ((pAd->OpMode == OPMODE_STA) && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL))
382 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
384 bAckRequired = FALSE;
386 else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
389 //pHeader_802_11->Sequence = pAd->Sequence;
391 if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
393 bAckRequired = FALSE;
394 pHeader_802_11->Duration = 0;
399 pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
400 if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP) && (pHeader_802_11->FC.Type == BTYPE_MGMT))
402 bInsertTimestamp = TRUE;
403 bAckRequired = FALSE; // Disable ACK to prevent retry 0x1f for Probe Response
405 else if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_REQ) && (pHeader_802_11->FC.Type == BTYPE_MGMT))
407 bAckRequired = FALSE; // Disable ACK to prevent retry 0x1f for Probe Request
412 pHeader_802_11->Sequence = pAd->Sequence++;
413 if (pAd->Sequence >0xfff)
416 // Before radar detection done, mgmt frame can not be sent but probe req
417 // Because we need to use probe req to trigger driver to send probe req in passive scan
418 if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
419 && (pAd->CommonCfg.bIEEE80211H == 1)
420 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
422 DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
424 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
425 return (NDIS_STATUS_FAILURE);
430 // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
431 // should always has only one physical buffer, and the whole frame size equals
432 // to the first scatter buffer size
435 // Initialize TX Descriptor
436 // For inter-frame gap, the number is for this frame and next frame
437 // For MLME rate, we will fix as 2Mb to match other vendor's implement
438 // pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
440 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
444 if (pMacEntry == NULL)
446 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
447 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
451 /* dont use low rate to send QoS Null data frame */
452 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
453 bInsertTimestamp, FALSE, bAckRequired, FALSE,
454 0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE),
455 pMacEntry->MaxHTPhyMode.field.MCS, 0,
456 (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
457 IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
460 // Now do hardware-depened kick out.
461 HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen);
463 // Make sure to release MGMT ring resource
465 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
466 return NDIS_STATUS_SUCCESS;
470 /********************************************************************************
472 New DeQueue Procedures.
474 ********************************************************************************/
476 #define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \
478 if (bIntContext == FALSE) \
479 RTMP_IRQ_LOCK((lock), IrqFlags); \
482 #define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \
484 if (bIntContext == FALSE) \
485 RTMP_IRQ_UNLOCK((lock), IrqFlags); \
489 ========================================================================
490 Tx Path design algorithm:
491 Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal),
492 Specific Packet Type. Following show the classification rule and policy for each kinds of packets.
493 Classification Rule=>
494 Multicast: (*addr1 & 0x01) == 0x01
495 Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc.
496 11N Rate : If peer support HT
497 (1).AMPDU -- If TXBA is negotiated.
498 (2).AMSDU -- If AMSDU is capable for both peer and ourself.
499 *). AMSDU can embedded in a AMPDU, but now we didn't support it.
500 (3).Normal -- Other packets which send as 11n rate.
502 B/G Rate : If peer is b/g only.
503 (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6
504 (2).Normal -- Other packets which send as b/g rate.
506 The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
508 Classified Packet Handle Rule=>
510 No ACK, //pTxBlk->bAckRequired = FALSE;
511 No WMM, //pTxBlk->bWMM = FALSE;
512 No piggyback, //pTxBlk->bPiggyBack = FALSE;
513 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
514 Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use
515 the same policy to handle it.
516 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
519 No piggyback, //pTxBlk->bPiggyBack = FALSE;
531 ========================================================================
533 static UCHAR TxPktClassification(
534 IN RTMP_ADAPTER *pAd,
535 IN PNDIS_PACKET pPacket)
537 UCHAR TxFrameType = TX_UNKOWN_FRAME;
539 MAC_TABLE_ENTRY *pMacEntry = NULL;
540 BOOLEAN bHTRate = FALSE;
542 Wcid = RTMP_GET_PACKET_WCID(pPacket);
543 if (Wcid == MCAST_WCID)
544 { // Handle for RA is Broadcast/Multicast Address.
545 return TX_MCAST_FRAME;
548 // Handle for unicast packets
549 pMacEntry = &pAd->MacTab.Content[Wcid];
550 if (RTMP_GET_PACKET_LOWRATE(pPacket))
551 { // It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame
552 TxFrameType = TX_LEGACY_FRAME;
554 else if (IS_HT_RATE(pMacEntry))
555 { // it's a 11n capable packet
557 // Depends on HTPhyMode to check if the peer support the HTRate transmission.
558 // Currently didn't support A-MSDU embedded in A-MPDU
560 if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE))
561 TxFrameType = TX_LEGACY_FRAME;
562 else if((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0)
563 return TX_AMPDU_FRAME;
564 else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED))
565 return TX_AMSDU_FRAME;
567 TxFrameType = TX_LEGACY_FRAME;
570 { // it's a legacy b/g packet.
571 if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) &&
572 (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) &&
573 (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
574 { // if peer support Ralink Aggregation, we use it.
575 TxFrameType = TX_RALINK_FRAME;
579 TxFrameType = TX_LEGACY_FRAME;
583 // Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU.
584 if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) && (TxFrameType == TX_LEGACY_FRAME))
585 TxFrameType = TX_FRAG_FRAME;
591 BOOLEAN RTMP_FillTxBlkInfo(
592 IN RTMP_ADAPTER *pAd,
595 PACKET_INFO PacketInfo;
596 PNDIS_PACKET pPacket;
597 PMAC_TABLE_ENTRY pMacEntry = NULL;
599 pPacket = pTxBlk->pPacket;
600 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
602 pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket);
603 pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket);
604 pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket);
605 pTxBlk->FrameGap = IFS_HTTXOP; // ASIC determine Frame Gap
607 if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket))
608 TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame);
610 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame);
612 // Default to clear this flag
613 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS);
616 if (pTxBlk->Wcid == MCAST_WCID)
618 pTxBlk->pMacEntry = NULL;
620 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
623 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); // AckRequired = FALSE, when broadcast packet in Adhoc mode.
624 //TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate);
625 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag);
626 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
627 if (RTMP_GET_PACKET_MOREDATA(pPacket))
629 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
635 pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
636 pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode;
638 pMacEntry = pTxBlk->pMacEntry;
641 // For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK.
642 if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK)
643 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
645 TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired);
647 if ((pAd->OpMode == OPMODE_STA) &&
649 (RX_FILTER_TEST_FLAG(pAd, fRX_FILTER_ACCEPT_PROMISCUOUS)))
651 if(pAd->CommonCfg.PSPXlink)
652 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
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 // if (pAd->StaCfg.bAutoTxRateSwitch)
664 // TX_BLK_SET_FLAG(pTxBlk, fTX_AutoRateSwitch);
668 if (pTxBlk->TxFrameType == TX_LEGACY_FRAME)
670 if ( (RTMP_GET_PACKET_LOWRATE(pPacket)) ||
671 ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1)))
672 { // Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate.
673 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
675 // Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it???
676 if (IS_HT_STA(pTxBlk->pMacEntry) &&
677 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) &&
678 ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)))
680 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
681 TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS);
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);
691 if (RTMP_GET_PACKET_MOREDATA(pPacket))
693 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
696 else if (pTxBlk->TxFrameType == TX_FRAG_FRAME)
698 TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag);
701 pMacEntry->DebugTxCount++;
708 BOOLEAN CanDoAggregateTransmit(
709 IN RTMP_ADAPTER *pAd,
710 IN NDIS_PACKET *pPacket,
714 //DBGPRINT(RT_DEBUG_TRACE, ("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType));
716 if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
719 if (RTMP_GET_PACKET_DHCP(pPacket) ||
720 RTMP_GET_PACKET_EAPOL(pPacket) ||
721 RTMP_GET_PACKET_WAI(pPacket))
724 if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) &&
725 ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100)))
726 { // For AMSDU, allow the packets with total length < max-amsdu size
730 if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) &&
731 (pTxBlk->TxPacketList.Number == 2))
732 { // For RALINK-Aggregation, allow two frames in one batch.
736 if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP
745 ========================================================================
748 To do the enqueue operation and extract the first item of waiting
749 list. If a number of available shared memory segments could meet
750 the request of extracted item, the extracted item will be fragmented
751 into shared memory segments.
754 pAd Pointer to our adapter
755 pQueue Pointer to Waiting Queue
760 IRQL = DISPATCH_LEVEL
764 ========================================================================
766 VOID RTMPDeQueuePacket(
767 IN PRTMP_ADAPTER pAd,
768 IN BOOLEAN bIntContext,
769 IN UCHAR QIdx, /* BulkOutPipeId */
770 IN UCHAR Max_Tx_Packets)
772 PQUEUE_ENTRY pEntry = NULL;
773 PNDIS_PACKET pPacket;
774 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
776 PQUEUE_HEADER pQueue;
777 ULONG FreeNumber[NUM_OF_TX_RING];
778 UCHAR QueIdx, sQIdx, eQIdx;
779 unsigned long IrqFlags = 0;
780 BOOLEAN hasTxDesc = FALSE;
786 if (QIdx == NUM_OF_TX_RING)
789 eQIdx = 3; // 4 ACs, start from 0.
793 sQIdx = eQIdx = QIdx;
796 for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++)
800 RTMP_START_DEQUEUE(pAd, QueIdx, IrqFlags);
805 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |
806 fRTMP_ADAPTER_RADIO_OFF |
807 fRTMP_ADAPTER_RESET_IN_PROGRESS |
808 fRTMP_ADAPTER_HALT_IN_PROGRESS |
809 fRTMP_ADAPTER_NIC_NOT_EXIST))))
811 RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
815 if (Count >= Max_Tx_Packets)
818 DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
819 if (&pAd->TxSwQueue[QueIdx] == NULL)
821 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
826 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
829 if (FreeNumber[QueIdx] <= 5)
831 // free Tx(QueIdx) resources
832 RTMPFreeTXDUponTxDmaDone(pAd, QueIdx);
833 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
835 #endif // RTMP_MAC_PCI //
837 // probe the Queue Head
838 pQueue = &pAd->TxSwQueue[QueIdx];
839 if ((pEntry = pQueue->Head) == NULL)
841 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
846 NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK));
847 //InitializeQueueHeader(&pTxBlk->TxPacketList); // Didn't need it because we already memzero it.
848 pTxBlk->QueIdx = QueIdx;
850 pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
853 // Early check to make sure we have enoguh Tx Resource.
854 hasTxDesc = RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
857 pAd->PrivateInfo.TxRingFullCnt++;
859 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
864 pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
865 pEntry = RemoveHeadQueue(pQueue);
866 pTxBlk->TotalFrameNum++;
867 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
868 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
869 pTxBlk->pPacket = pPacket;
870 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
872 if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME)
874 // Enhance SW Aggregation Mechanism
875 if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType))
877 InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
878 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
883 if((pEntry = pQueue->Head) == NULL)
886 // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation.
887 pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
888 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
889 hasTxDesc = RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
890 if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE))
893 //Remove the packet from the TxSwQueue and insert into pTxBlk
894 pEntry = RemoveHeadQueue(pQueue);
896 pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
897 pTxBlk->TotalFrameNum++;
898 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
899 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
900 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
903 if (pTxBlk->TxPacketList.Number == 1)
904 pTxBlk->TxFrameType = TX_LEGACY_FRAME;
908 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
909 #endif // RTMP_MAC_USB //
910 Count += pTxBlk->TxPacketList.Number;
912 // Do HardTransmit now.
913 Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
916 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
917 // static rate also need NICUpdateFifoStaCounters() function.
918 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
919 NICUpdateFifoStaCounters(pAd);
920 #endif // RTMP_MAC_PCI //
924 RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
928 RTUSBKickBulkOut(pAd);
929 #endif // RTMP_MAC_USB //
936 ========================================================================
939 Calculates the duration which is required to transmit out frames
940 with given size and specified rate.
943 pAd Pointer to our adapter
945 Size Frame size in units of byte
948 Duration number in units of usec
951 IRQL = DISPATCH_LEVEL
955 ========================================================================
957 USHORT RTMPCalcDuration(
958 IN PRTMP_ADAPTER pAd,
964 if (Rate < RATE_FIRST_OFDM_RATE) // CCK
966 if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED))
967 Duration = 96; // 72+24 preamble+plcp
969 Duration = 192; // 144+48 preamble+plcp
971 Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]);
972 if ((Size << 4) % RateIdTo500Kbps[Rate])
975 else if (Rate <= RATE_LAST_OFDM_RATE)// OFDM rates
977 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
978 Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
979 if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
984 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
987 return (USHORT)Duration;
992 ========================================================================
995 Calculates the duration which is required to transmit out frames
996 with given size and specified rate.
999 pTxWI Pointer to head of each MPDU to HW.
1000 Ack Setting for Ack requirement bit
1001 Fragment Setting for Fragment bit
1002 RetryMode Setting for retry mode
1003 Ifs Setting for IFS gap
1004 Rate Setting for transmit rate
1005 Service Setting for service
1007 TxPreamble Short or Long preamble when using CCK rates
1008 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1013 IRQL = PASSIVE_LEVEL
1014 IRQL = DISPATCH_LEVEL
1016 See also : BASmartHardTransmit() !!!
1018 ========================================================================
1021 IN PRTMP_ADAPTER pAd,
1022 IN PTXWI_STRUC pOutTxWI,
1025 IN BOOLEAN InsTimestamp,
1028 IN BOOLEAN NSeq, // HW new a sequence.
1037 IN HTTRANSMIT_SETTING *pTransmit)
1039 PMAC_TABLE_ENTRY pMac = NULL;
1043 if (WCID < MAX_LEN_OF_MAC_TABLE)
1044 pMac = &pAd->MacTab.Content[WCID];
1047 // Always use Long preamble before verifiation short preamble functionality works well.
1048 // Todo: remove the following line if short preamble functionality works
1050 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1051 NdisZeroMemory(&TxWI, TXWI_SIZE);
1056 pTxWI->CFACK = CFACK;
1057 pTxWI->TS= InsTimestamp;
1058 pTxWI->AMPDU = AMPDU;
1060 pTxWI->txop= Txopmode;
1063 // John tune the performace with Intel Client in 20 MHz performance
1064 BASize = pAd->CommonCfg.TxBASize;
1065 if (pAd->MACVersion == 0x28720200)
1075 pTxWI->BAWinSize = BASize;
1076 pTxWI->ShortGI = pTransmit->field.ShortGI;
1077 pTxWI->STBC = pTransmit->field.STBC;
1079 pTxWI->WirelessCliID = WCID;
1080 pTxWI->MPDUtotalByteCount = Length;
1081 pTxWI->PacketId = PID;
1083 // If CCK or OFDM, BW must be 20
1084 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1086 pTxWI->MCS = pTransmit->field.MCS;
1087 pTxWI->PHYMODE = pTransmit->field.MODE;
1088 pTxWI->CFACK = CfAck;
1092 if (pAd->CommonCfg.bMIMOPSEnable)
1094 if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1096 // Dynamic MIMO Power Save Mode
1099 else if (pMac->MmpsMode == MMPS_STATIC)
1101 // Static MIMO Power Save Mode
1102 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1109 //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;
1110 if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled))
1112 pTxWI->MpduDensity = 7;
1116 pTxWI->MpduDensity = pMac->MpduDensity;
1120 pTxWI->PacketId = pTxWI->MCS;
1121 NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC));
1125 VOID RTMPWriteTxWI_Data(
1126 IN PRTMP_ADAPTER pAd,
1127 IN OUT PTXWI_STRUC pTxWI,
1130 HTTRANSMIT_SETTING *pTransmit;
1131 PMAC_TABLE_ENTRY pMacEntry;
1136 pTransmit = pTxBlk->pTransmit;
1137 pMacEntry = pTxBlk->pMacEntry;
1141 // Always use Long preamble before verifiation short preamble functionality works well.
1142 // Todo: remove the following line if short preamble functionality works
1144 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1145 NdisZeroMemory(pTxWI, TXWI_SIZE);
1147 pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1148 pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1149 pTxWI->txop = pTxBlk->FrameGap;
1151 pTxWI->WirelessCliID = pTxBlk->Wcid;
1153 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1154 pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
1156 // If CCK or OFDM, BW must be 20
1157 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1158 pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
1160 // John tune the performace with Intel Client in 20 MHz performance
1161 BASize = pAd->CommonCfg.TxBASize;
1162 if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry))
1164 UCHAR RABAOriIdx = 0; //The RA's BA Originator table index.
1166 RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
1167 BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1170 pTxWI->TxBF = pTransmit->field.TxBF;
1171 pTxWI->BAWinSize = BASize;
1172 pTxWI->ShortGI = pTransmit->field.ShortGI;
1173 pTxWI->STBC = pTransmit->field.STBC;
1175 pTxWI->MCS = pTransmit->field.MCS;
1176 pTxWI->PHYMODE = pTransmit->field.MODE;
1180 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1182 // Dynamic MIMO Power Save Mode
1185 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1187 // Static MIMO Power Save Mode
1188 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1195 if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled))
1197 pTxWI->MpduDensity = 7;
1201 pTxWI->MpduDensity = pMacEntry->MpduDensity;
1206 // for rate adapation
1207 pTxWI->PacketId = pTxWI->MCS;
1211 VOID RTMPWriteTxWI_Cache(
1212 IN PRTMP_ADAPTER pAd,
1213 IN OUT PTXWI_STRUC pTxWI,
1216 PHTTRANSMIT_SETTING /*pTxHTPhyMode,*/ pTransmit;
1217 PMAC_TABLE_ENTRY pMacEntry;
1222 pMacEntry = pTxBlk->pMacEntry;
1223 pTransmit = pTxBlk->pTransmit;
1225 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
1226 //if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pMacEntry))
1227 //if (TX_BLK_TEST_FLAG(pTxBlk, fTX_AutoRateSwitch))
1228 if (pMacEntry->bAutoTxRateSwitch)
1230 pTxWI->txop = IFS_HTTXOP;
1232 // If CCK or OFDM, BW must be 20
1233 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1234 pTxWI->ShortGI = pTransmit->field.ShortGI;
1235 pTxWI->STBC = pTransmit->field.STBC;
1237 pTxWI->MCS = pTransmit->field.MCS;
1238 pTxWI->PHYMODE = pTransmit->field.MODE;
1240 // set PID for TxRateSwitching
1241 pTxWI->PacketId = pTransmit->field.MCS;
1244 pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE);
1247 if (pAd->CommonCfg.bMIMOPSEnable)
1249 // MIMO Power Save Mode
1250 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1252 // Dynamic MIMO Power Save Mode
1255 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1257 // Static MIMO Power Save Mode
1258 if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7))
1267 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1272 // should be called only when -
1273 // 1. MEADIA_CONNECTED
1274 // 2. AGGREGATION_IN_USED
1275 // 3. Fragmentation not in used
1276 // 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible
1277 BOOLEAN TxFrameIsAggregatible(
1278 IN PRTMP_ADAPTER pAd,
1279 IN PUCHAR pPrevAddr1,
1283 // can't aggregate EAPOL (802.1x) frame
1284 if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1287 // can't aggregate multicast/broadcast frame
1288 if (p8023hdr[0] & 0x01)
1291 if (INFRA_ON(pAd)) // must be unicast to AP
1293 else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA
1301 ========================================================================
1303 Routine Description:
1304 Check the MSDU Aggregation policy
1305 1.HT aggregation is A-MSDU
1306 2.legaacy rate aggregation is software aggregation by Ralink.
1314 ========================================================================
1316 BOOLEAN PeerIsAggreOn(
1317 IN PRTMP_ADAPTER pAd,
1319 IN PMAC_TABLE_ENTRY pMacEntry)
1321 ULONG AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
1323 if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags))
1325 if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX)
1330 #ifdef AGGREGATION_SUPPORT
1331 if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
1332 { // legacy Ralink Aggregation support
1335 #endif // AGGREGATION_SUPPORT //
1344 ========================================================================
1346 Routine Description:
1347 Check and fine the packet waiting in SW queue with highest priority
1350 pAd Pointer to our adapter
1353 pQueue Pointer to Waiting Queue
1355 IRQL = DISPATCH_LEVEL
1359 ========================================================================
1361 PQUEUE_HEADER RTMPCheckTxSwQueue(
1362 IN PRTMP_ADAPTER pAd,
1367 // 2004-11-15 to be removed. test aggregation only
1368 // if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2))
1371 Number = pAd->TxSwQueue[QID_AC_BK].Number
1372 + pAd->TxSwQueue[QID_AC_BE].Number
1373 + pAd->TxSwQueue[QID_AC_VI].Number
1374 + pAd->TxSwQueue[QID_AC_VO].Number;
1376 if (pAd->TxSwQueue[QID_AC_VO].Head != NULL)
1378 *pQueIdx = QID_AC_VO;
1379 return (&pAd->TxSwQueue[QID_AC_VO]);
1381 else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL)
1383 *pQueIdx = QID_AC_VI;
1384 return (&pAd->TxSwQueue[QID_AC_VI]);
1386 else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL)
1388 *pQueIdx = QID_AC_BE;
1389 return (&pAd->TxSwQueue[QID_AC_BE]);
1391 else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL)
1393 *pQueIdx = QID_AC_BK;
1394 return (&pAd->TxSwQueue[QID_AC_BK]);
1397 // No packet pending in Tx Sw queue
1398 *pQueIdx = QID_AC_BK;
1405 ========================================================================
1407 Routine Description:
1408 Suspend MSDU transmission
1411 pAd Pointer to our adapter
1418 ========================================================================
1420 VOID RTMPSuspendMsduTransmission(
1421 IN PRTMP_ADAPTER pAd)
1423 DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n"));
1427 // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
1428 // use Lowbound as R66 value on ScanNextChannel(...)
1430 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue);
1432 // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)
1433 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd)));
1434 RTMPSetAGCInitValue(pAd, BW_20);
1436 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1437 //RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000); // abort all TX rings
1442 ========================================================================
1444 Routine Description:
1445 Resume MSDU transmission
1448 pAd Pointer to our adapter
1453 IRQL = DISPATCH_LEVEL
1457 ========================================================================
1459 VOID RTMPResumeMsduTransmission(
1460 IN PRTMP_ADAPTER pAd)
1464 DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
1467 // After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value
1468 // R66 should not be 0
1469 if (pAd->BbpTuning.R66CurrentValue == 0)
1471 pAd->BbpTuning.R66CurrentValue = 0x38;
1472 DBGPRINT_ERR(("RTMPResumeMsduTransmission, R66CurrentValue=0...\n"));
1475 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue);
1477 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1478 // sample, for IRQ LOCK to SEM LOCK
1479 // IrqState = pAd->irq_disabled;
1481 // RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1483 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1487 UINT deaggregate_AMSDU_announce(
1488 IN PRTMP_ADAPTER pAd,
1489 PNDIS_PACKET pPacket,
1494 USHORT SubFrameSize;
1495 PHEADER_802_3 pAMSDUsubheader;
1497 UCHAR Header802_3[14];
1499 PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP;
1500 PNDIS_PACKET pClonePacket;
1506 while (DataSize > LENGTH_802_3)
1511 //hex_dump("subheader", pData, 64);
1512 pAMSDUsubheader = (PHEADER_802_3)pData;
1513 //pData += LENGTH_802_3;
1514 PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8);
1515 SubFrameSize = PayloadSize + LENGTH_802_3;
1518 if ((DataSize < SubFrameSize) || (PayloadSize > 1518 ))
1523 //DBGPRINT(RT_DEBUG_TRACE,("%d subframe: Size = %d\n", nMSDU, PayloadSize));
1525 pPayload = pData + LENGTH_802_3;
1527 pSA = pData + MAC_ADDR_LEN;
1529 // convert to 802.3 header
1530 CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP);
1532 if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) )
1534 /* avoid local heap overflow, use dyanamic allocation */
1535 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
1538 memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize);
1539 Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize;
1540 //WpaEAPOLKeyAction(pAd, Elem);
1541 REPORT_MGMT_FRAME_TO_MLME(pAd, BSSID_WCID, Elem->Msg, Elem->MsgLen, 0, 0, 0, 0);
1547 if (pRemovedLLCSNAP)
1549 pPayload -= LENGTH_802_3;
1550 PayloadSize += LENGTH_802_3;
1551 NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3);
1555 pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
1558 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket));
1562 // A-MSDU has padding to multiple of 4 including subframe header.
1563 // align SubFrameSize up to multiple of 4
1564 SubFrameSize = (SubFrameSize+3)&(~0x3);
1567 if (SubFrameSize > 1528 || SubFrameSize < 32)
1572 if (DataSize > SubFrameSize)
1574 pData += SubFrameSize;
1575 DataSize -= SubFrameSize;
1584 // finally release original rx packet
1585 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1591 UINT BA_Reorder_AMSDU_Annnounce(
1592 IN PRTMP_ADAPTER pAd,
1593 IN PNDIS_PACKET pPacket)
1599 pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
1600 DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
1602 nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
1609 ==========================================================================
1611 Look up the MAC address in the MAC table. Return NULL if not found.
1613 pEntry - pointer to the MAC entry; NULL is not found
1614 ==========================================================================
1616 MAC_TABLE_ENTRY *MacTableLookup(
1617 IN PRTMP_ADAPTER pAd,
1621 MAC_TABLE_ENTRY *pEntry = NULL;
1623 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1624 pEntry = pAd->MacTab.Hash[HashIdx];
1626 while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh))
1628 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1633 pEntry = pEntry->pNext;
1639 MAC_TABLE_ENTRY *MacTableInsertEntry(
1640 IN PRTMP_ADAPTER pAd,
1643 IN BOOLEAN CleanAll)
1647 MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
1652 if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
1657 if (pAd->StaCfg.BssType == BSS_INFRA)
1660 // allocate one MAC entry
1661 NdisAcquireSpinLock(&pAd->MacTabLock);
1662 for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++) // skip entry#0 so that "entry index == AID" for fast lookup
1664 // pick up the first available vacancy
1665 if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
1666 (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
1667 (pAd->MacTab.Content[i].ValidAsApCli== FALSE) &&
1668 (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
1671 pEntry = &pAd->MacTab.Content[i];
1672 if (CleanAll == TRUE)
1674 pEntry->MaxSupportedRate = RATE_11;
1675 pEntry->CurrTxRate = RATE_11;
1676 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1677 pEntry->PairwiseKey.KeyLen = 0;
1678 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1682 pEntry->ValidAsCLI = TRUE;
1683 pEntry->ValidAsWDS = FALSE;
1684 pEntry->ValidAsApCli = FALSE;
1685 pEntry->ValidAsMesh = FALSE;
1686 pEntry->ValidAsDls = FALSE;
1690 pEntry->bIAmBadAtheros = FALSE;
1692 pEntry->CMTimerRunning = FALSE;
1693 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
1694 pEntry->RSNIE_Len = 0;
1695 NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
1696 pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
1698 if (pEntry->ValidAsMesh)
1699 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH);
1700 else if (pEntry->ValidAsApCli)
1701 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI);
1702 else if (pEntry->ValidAsWDS)
1703 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS);
1705 pEntry->apidx = apidx;
1709 pEntry->AuthMode = pAd->StaCfg.AuthMode;
1710 pEntry->WepStatus = pAd->StaCfg.WepStatus;
1711 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
1713 AsicRemovePairwiseKeyEntry(pAd, pEntry->apidx, (UCHAR)i);
1714 #endif // RTMP_MAC_PCI //
1718 pEntry->GTKState = REKEY_NEGOTIATING;
1719 pEntry->PairwiseKey.KeyLen = 0;
1720 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1721 pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
1723 pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
1724 COPY_MAC_ADDR(pEntry->Addr, pAddr);
1725 pEntry->Sst = SST_NOT_AUTH;
1726 pEntry->AuthState = AS_NOT_AUTH;
1727 pEntry->Aid = (USHORT)i; //0;
1728 pEntry->CapabilityInfo = 0;
1729 pEntry->PsMode = PWR_ACTIVE;
1730 pEntry->PsQIdleCount = 0;
1731 pEntry->NoDataIdleCount = 0;
1732 pEntry->AssocDeadLine = MAC_TABLE_ASSOC_TIMEOUT;
1733 pEntry->ContinueTxFailCnt = 0;
1734 InitializeQueueHeader(&pEntry->PsQueue);
1737 pAd->MacTab.Size ++;
1738 // Add this entry into ASIC RX WCID search table
1739 RTMP_STA_ENTRY_ADD(pAd, pEntry);
1743 DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size));
1748 // add this MAC entry into HASH table
1751 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1752 if (pAd->MacTab.Hash[HashIdx] == NULL)
1754 pAd->MacTab.Hash[HashIdx] = pEntry;
1758 pCurrEntry = pAd->MacTab.Hash[HashIdx];
1759 while (pCurrEntry->pNext != NULL)
1760 pCurrEntry = pCurrEntry->pNext;
1761 pCurrEntry->pNext = pEntry;
1765 NdisReleaseSpinLock(&pAd->MacTabLock);
1770 ==========================================================================
1772 Delete a specified client from MAC table
1773 ==========================================================================
1775 BOOLEAN MacTableDeleteEntry(
1776 IN PRTMP_ADAPTER pAd,
1781 MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
1783 //USHORT offset; // unused variable
1784 //UCHAR j; // unused variable
1786 if (wcid >= MAX_LEN_OF_MAC_TABLE)
1789 NdisAcquireSpinLock(&pAd->MacTabLock);
1791 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1792 //pEntry = pAd->MacTab.Hash[HashIdx];
1793 pEntry = &pAd->MacTab.Content[wcid];
1795 if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh
1798 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1801 // Delete this entry from ASIC on-chip WCID Table
1802 RTMP_STA_ENTRY_MAC_RESET(pAd, wcid);
1804 // free resources of BA
1805 BASessionTearDownALL(pAd, pEntry->Aid);
1808 pProbeEntry = pAd->MacTab.Hash[HashIdx];
1809 ASSERT(pProbeEntry);
1814 if (pProbeEntry == pEntry)
1816 if (pPrevEntry == NULL)
1818 pAd->MacTab.Hash[HashIdx] = pEntry->pNext;
1822 pPrevEntry->pNext = pEntry->pNext;
1827 pPrevEntry = pProbeEntry;
1828 pProbeEntry = pProbeEntry->pNext;
1829 } while (pProbeEntry);
1832 ASSERT(pProbeEntry != NULL);
1834 RTMP_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
1837 if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
1839 RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
1840 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
1844 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1845 pAd->MacTab.Size --;
1846 DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size));
1850 DBGPRINT(RT_DEBUG_OFF, ("\n%s: Impossible Wcid = %d !!!!!\n", __func__, wcid));
1854 NdisReleaseSpinLock(&pAd->MacTabLock);
1856 //Reset operating mode when no Sta.
1857 if (pAd->MacTab.Size == 0)
1859 pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
1860 //AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/);
1861 RTMP_UPDATE_PROTECT(pAd); // edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet
1869 ==========================================================================
1871 This routine reset the entire MAC table. All packets pending in
1872 the power-saving queues are freed here.
1873 ==========================================================================
1876 IN PRTMP_ADAPTER pAd)
1880 DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
1881 //NdisAcquireSpinLock(&pAd->MacTabLock);
1884 for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
1887 RTMP_STA_ENTRY_MAC_RESET(pAd, i);
1888 #endif // RTMP_MAC_PCI //
1889 if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
1893 // free resources of BA
1894 BASessionTearDownALL(pAd, i);
1896 pAd->MacTab.Content[i].ValidAsCLI = FALSE;
1899 NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6);
1900 RTMP_STA_ENTRY_MAC_RESET(pAd, i);
1901 #endif // RTMP_MAC_USB //
1903 //AsicDelWcidTab(pAd, i);
1911 ==========================================================================
1914 IRQL = DISPATCH_LEVEL
1916 ==========================================================================
1919 IN PRTMP_ADAPTER pAd,
1920 IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
1922 IN USHORT CapabilityInfo,
1924 IN USHORT ListenIntv)
1926 COPY_MAC_ADDR(AssocReq->Addr, pAddr);
1927 // Add mask to support 802.11b mode only
1928 AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request
1929 AssocReq->Timeout = Timeout;
1930 AssocReq->ListenIntv = ListenIntv;
1935 ==========================================================================
1938 IRQL = DISPATCH_LEVEL
1940 ==========================================================================
1942 VOID DisassocParmFill(
1943 IN PRTMP_ADAPTER pAd,
1944 IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
1948 COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
1949 DisassocReq->Reason = Reason;
1954 ========================================================================
1956 Routine Description:
1957 Check the out going frame, if this is an DHCP or ARP datagram
1958 will be duplicate another frame at low data rate transmit.
1961 pAd Pointer to our adapter
1962 pPacket Pointer to outgoing Ndis frame
1965 TRUE To be duplicate at Low data rate transmit. (1mb)
1968 IRQL = DISPATCH_LEVEL
1972 MAC header + IP Header + UDP Header
1976 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
1978 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
1981 port 0x43 means Bootstrap Protocol, server.
1982 Port 0x44 means Bootstrap Protocol, client.
1984 ========================================================================
1987 BOOLEAN RTMPCheckDHCPFrame(
1988 IN PRTMP_ADAPTER pAd,
1989 IN PNDIS_PACKET pPacket)
1991 PACKET_INFO PacketInfo;
1992 ULONG NumberOfBytesRead = 0;
1993 ULONG CurrentOffset = 0;
1994 PVOID pVirtualAddress = NULL;
1995 UINT NdisBufferLength;
1998 UCHAR ByteOffset36 = 0;
1999 UCHAR ByteOffset38 = 0;
2000 BOOLEAN ReadFirstParm = TRUE;
2002 RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength);
2004 NumberOfBytesRead += NdisBufferLength;
2005 pSrc = (PUCHAR) pVirtualAddress;
2006 Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
2009 // Check DHCP & BOOTP protocol
2011 while (NumberOfBytesRead <= PacketInfo.TotalPacketLength)
2013 if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE))
2015 CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength);
2016 ByteOffset36 = *(pSrc + CurrentOffset);
2017 ReadFirstParm = FALSE;
2020 if (NumberOfBytesRead >= 37)
2022 CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength);
2023 ByteOffset38 = *(pSrc + CurrentOffset);
2030 // Check for DHCP & BOOTP protocol
2031 if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43))
2034 // 2054 (hex 0806) for ARP datagrams
2035 // if this packet is not ARP datagrams, then do nothing
2036 // ARP datagrams will also be duplicate at 1mb broadcast frames
2038 if (Protocol != 0x0806 )
2046 BOOLEAN RTMPCheckEtherType(
2047 IN PRTMP_ADAPTER pAd,
2048 IN PNDIS_PACKET pPacket)
2054 UINT16 srcPort, dstPort;
2055 BOOLEAN status = TRUE;
2058 pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
2059 pktLen = GET_OS_PKT_LEN(pPacket);
2063 RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
2065 // get Ethernet protocol field
2066 TypeLen = (pSrcBuf[12] << 8) | pSrcBuf[13];
2068 pSrcBuf += LENGTH_802_3; // Skip the Ethernet Header.
2070 if (TypeLen <= 1500)
2071 { // 802.3, 802.3 LLC
2073 DestMAC(6) + SrcMAC(6) + Lenght(2) +
2074 DSAP(1) + SSAP(1) + Control(1) +
2075 if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
2076 => + SNAP (5, OriginationID(3) + etherType(2))
2078 if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03)
2080 Sniff2BytesFromNdisBuffer((PNDIS_BUFFER)pSrcBuf, 6, &Byte0, &Byte1);
2081 RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
2082 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2083 pSrcBuf += 8; // Skip this LLC/SNAP header
2087 //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.
2091 // If it's a VLAN packet, get the real Type/Length field.
2092 if (TypeLen == 0x8100)
2094 /* 0x8100 means VLAN packets */
2096 /* Dest. MAC Address (6-bytes) +
2097 Source MAC Address (6-bytes) +
2098 Length/Type = 802.1Q Tag Type (2-byte) +
2099 Tag Control Information (2-bytes) +
2100 Length / Type (2-bytes) +
2101 data payload (0-n bytes) +
2103 Frame Check Sequence (4-bytes) */
2105 RTMP_SET_PACKET_VLAN(pPacket, 1);
2106 Sniff2BytesFromNdisBuffer((PNDIS_BUFFER)pSrcBuf, 2, &Byte0, &Byte1);
2107 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2109 pSrcBuf += 4; // Skip the VLAN Header.
2116 ASSERT((pktLen > 34));
2117 if (*(pSrcBuf + 9) == 0x11)
2119 ASSERT((pktLen > 34)); // 14 for ethernet header, 20 for IP header
2121 pSrcBuf += 20; // Skip the IP header
2122 srcPort = OS_NTOHS(get_unaligned((PUINT16)(pSrcBuf)));
2123 dstPort = OS_NTOHS(get_unaligned((PUINT16)(pSrcBuf+2)));
2125 if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44))
2126 { //It's a BOOTP/DHCP packet
2127 RTMP_SET_PACKET_DHCP(pPacket, 1);
2135 RTMP_SET_PACKET_DHCP(pPacket, 1);
2141 RTMP_SET_PACKET_EAPOL(pPacket, 1);
2155 VOID Update_Rssi_Sample(
2156 IN PRTMP_ADAPTER pAd,
2157 IN RSSI_SAMPLE *pRssi,
2158 IN PRXWI_STRUC pRxWI)
2160 CHAR rssi0 = pRxWI->RSSI0;
2161 CHAR rssi1 = pRxWI->RSSI1;
2162 CHAR rssi2 = pRxWI->RSSI2;
2166 pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0);
2167 pRssi->AvgRssi0X8 = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
2168 pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
2173 pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1);
2174 pRssi->AvgRssi1X8 = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
2175 pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
2180 pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2);
2181 pRssi->AvgRssi2X8 = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
2182 pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
2188 // Normal legacy Rx packet indication
2189 VOID Indicate_Legacy_Packet(
2190 IN PRTMP_ADAPTER pAd,
2192 IN UCHAR FromWhichBSSID)
2194 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2195 UCHAR Header802_3[LENGTH_802_3];
2197 // 1. get 802.3 Header
2199 // a. pointer pRxBlk->pData to payload
2200 // b. modify pRxBlk->DataSize
2201 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2203 if (pRxBlk->DataSize > MAX_RX_PKT_LEN)
2207 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2212 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
2215 if (pAd->CommonCfg.bDisableReordering == 0)
2217 PBA_REC_ENTRY pBAEntry;
2219 UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID;
2220 UCHAR TID = pRxBlk->pRxWI->TID;
2223 #define REORDERING_PACKET_TIMEOUT ((100 * OS_HZ)/1000) // system ticks -- 100 ms
2225 if (Wcid < MAX_LEN_OF_MAC_TABLE)
2227 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
2230 pBAEntry = &pAd->BATable.BARecEntry[Idx];
2231 // update last rx time
2232 NdisGetSystemUpTime(&Now32);
2233 if ((pBAEntry->list.qlen > 0) &&
2234 RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
2237 DBGPRINT(RT_DEBUG_OFF, ("Indicate_Legacy_Packet():flush reordering_timeout_mpdus! RxWI->Flags=%d, pRxWI.TID=%d, RxD->AMPDU=%d!\n",
2238 pRxBlk->Flags, pRxBlk->pRxWI->TID, pRxBlk->RxD.AMPDU));
2239 hex_dump("Dump the legacy Packet:", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), 64);
2240 ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
2245 #endif // RTMP_MAC_USB //
2247 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2250 // pass this 802.3 packet to upper layer or forward this packet to WM directly
2252 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
2256 // Normal, AMPDU or AMSDU
2257 VOID CmmRxnonRalinkFrameIndicate(
2258 IN PRTMP_ADAPTER pAd,
2260 IN UCHAR FromWhichBSSID)
2262 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
2264 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2268 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
2271 Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2275 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
2281 VOID CmmRxRalinkFrameIndicate(
2282 IN PRTMP_ADAPTER pAd,
2283 IN MAC_TABLE_ENTRY *pEntry,
2285 IN UCHAR FromWhichBSSID)
2287 UCHAR Header802_3[LENGTH_802_3];
2289 UINT16 Payload1Size, Payload2Size;
2291 PNDIS_PACKET pPacket2 = NULL;
2295 Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8);
2297 if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize))
2299 /* skip two byte MSDU2 len */
2301 pRxBlk->DataSize -= 2;
2306 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2310 // get 802.3 Header and remove LLC
2311 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2313 ASSERT(pRxBlk->pRxPacket);
2315 // Ralink Aggregation frame
2316 pAd->RalinkCounters.OneSecRxAggregationCount ++;
2317 Payload1Size = pRxBlk->DataSize - Msdu2Size;
2318 Payload2Size = Msdu2Size - LENGTH_802_3;
2320 pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
2322 pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID);
2327 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2331 // update payload size of 1st packet
2332 pRxBlk->DataSize = Payload1Size;
2333 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2335 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID);
2339 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
2344 #define RESET_FRAGFRAME(_fragFrame) \
2346 _fragFrame.RxSize = 0; \
2347 _fragFrame.Sequence = 0; \
2348 _fragFrame.LastFrag = 0; \
2349 _fragFrame.Flags = 0; \
2353 PNDIS_PACKET RTMPDeFragmentDataFrame(
2354 IN PRTMP_ADAPTER pAd,
2357 PHEADER_802_11 pHeader = pRxBlk->pHeader;
2358 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2359 UCHAR *pData = pRxBlk->pData;
2360 USHORT DataSize = pRxBlk->DataSize;
2361 PNDIS_PACKET pRetPacket = NULL;
2362 UCHAR *pFragBuffer = NULL;
2363 BOOLEAN bReassDone = FALSE;
2364 UCHAR HeaderRoom = 0;
2369 HeaderRoom = pData - (UCHAR *)pHeader;
2371 // Re-assemble the fragmented packets
2372 if (pHeader->Frag == 0) // Frag. Number is 0 : First frag or only one pkt
2374 // the first pkt of fragment, record it.
2375 if (pHeader->FC.MoreFrag)
2377 ASSERT(pAd->FragFrame.pFragPacket);
2378 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2379 pAd->FragFrame.RxSize = DataSize + HeaderRoom;
2380 NdisMoveMemory(pFragBuffer, pHeader, pAd->FragFrame.RxSize);
2381 pAd->FragFrame.Sequence = pHeader->Sequence;
2382 pAd->FragFrame.LastFrag = pHeader->Frag; // Should be 0
2383 ASSERT(pAd->FragFrame.LastFrag == 0);
2384 goto done; // end of processing this frame
2387 else //Middle & End of fragment
2389 if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
2390 (pHeader->Frag != (pAd->FragFrame.LastFrag + 1)))
2392 // Fragment is not the same sequence or out of fragment number order
2393 // Reset Fragment control blk
2394 RESET_FRAGFRAME(pAd->FragFrame);
2395 DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n"));
2396 goto done; // give up this frame
2398 else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE)
2400 // Fragment frame is too large, it exeeds the maximum frame size.
2401 // Reset Fragment control blk
2402 RESET_FRAGFRAME(pAd->FragFrame);
2403 DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
2404 goto done; // give up this frame
2408 // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.
2409 // In this case, we will dropt it.
2411 if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H)))
2413 DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag));
2414 goto done; // give up this frame
2417 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2419 // concatenate this fragment into the re-assembly buffer
2420 NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize);
2421 pAd->FragFrame.RxSize += DataSize;
2422 pAd->FragFrame.LastFrag = pHeader->Frag; // Update fragment number
2425 if (pHeader->FC.MoreFrag == FALSE)
2432 // always release rx fragmented packet
2433 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2435 // return defragmented packet if packet is reassembled completely
2436 // otherwise return NULL
2439 PNDIS_PACKET pNewFragPacket;
2441 // allocate a new packet buffer for fragment
2442 pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
2446 pRetPacket = pAd->FragFrame.pFragPacket;
2447 pAd->FragFrame.pFragPacket = pNewFragPacket;
2448 pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
2449 pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom;
2450 pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
2451 pRxBlk->pRxPacket = pRetPacket;
2455 RESET_FRAGFRAME(pAd->FragFrame);
2463 VOID Indicate_AMSDU_Packet(
2464 IN PRTMP_ADAPTER pAd,
2466 IN UCHAR FromWhichBSSID)
2470 update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
2471 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
2472 nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize);
2475 VOID Indicate_EAPOL_Packet(
2476 IN PRTMP_ADAPTER pAd,
2478 IN UCHAR FromWhichBSSID)
2480 MAC_TABLE_ENTRY *pEntry = NULL;
2483 pEntry = &pAd->MacTab.Content[BSSID_WCID];
2484 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
2490 DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
2492 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2497 #define BCN_TBTT_OFFSET 64 //defer 64 us
2498 VOID ReSyncBeaconTime(
2499 IN PRTMP_ADAPTER pAd)
2505 Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
2507 pAd->TbttTickCount++;
2510 // The updated BeaconInterval Value will affect Beacon Interval after two TBTT
2511 // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
2513 if (Offset == (BCN_TBTT_OFFSET-2))
2515 BCN_TIME_CFG_STRUC csr;
2516 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2517 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; // ASIC register in units of 1/16 TU = 64us
2518 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2522 if (Offset == (BCN_TBTT_OFFSET-1))
2524 BCN_TIME_CFG_STRUC csr;
2526 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2527 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU
2528 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);