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 UCHAR SNAP_802_1H[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
31 UCHAR SNAP_BRIDGE_TUNNEL[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
33 // Add Cisco Aironet SNAP heade for CCX2 support
34 UCHAR SNAP_AIRONET[] = { 0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00 };
35 UCHAR CKIP_LLC_SNAP[] = { 0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02 };
36 UCHAR EAPOL_LLC_SNAP[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e };
37 UCHAR EAPOL[] = { 0x88, 0x8e };
38 UCHAR TPID[] = { 0x81, 0x00 }; /* VLAN related */
40 UCHAR IPX[] = { 0x81, 0x37 };
41 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 */
47 }; // 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
62 UCHAR RxwiMCSToOfdmRate[12] = {
63 RATE_6, RATE_9, RATE_12, RATE_18,
64 RATE_24, RATE_36, RATE_48, RATE_54, // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3
65 4, 5, 6, 7, // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7
69 { "1Mbps", "2Mbps", "5.5Mbps", "11Mbps", "06Mbps", "09Mbps", "12Mbps",
70 "18Mbps", "24Mbps", "36Mbps", "48Mbps", "54Mbps", "MM-0", "MM-1", "MM-2", "MM-3",
71 "MM-4", "MM-5", "MM-6", "MM-7", "MM-8", "MM-9", "MM-10", "MM-11", "MM-12", "MM-13",
72 "MM-14", "MM-15", "MM-32", "ee1", "ee2", "ee3" };
74 UCHAR default_cwmin[] =
75 { CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS - 1, CW_MIN_IN_BITS - 2 };
76 //UCHAR default_cwmax[]={CW_MAX_IN_BITS, CW_MAX_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1};
77 UCHAR default_sta_aifsn[] = { 3, 7, 2, 2 };
79 UCHAR MapUserPriorityToAccessCategory[8] =
80 { QID_AC_BE, QID_AC_BK, QID_AC_BK, QID_AC_BE, QID_AC_VI, QID_AC_VI,
81 QID_AC_VO, QID_AC_VO };
84 ========================================================================
87 API for MLME to transmit management frame to AP (BSS Mode)
88 or station (IBSS Mode)
91 pAd Pointer to our adapter
92 pData Pointer to the outgoing 802.11 frame
93 Length Size of outgoing management frame
101 IRQL = DISPATCH_LEVEL
105 ========================================================================
107 NDIS_STATUS MiniportMMRequest(IN PRTMP_ADAPTER pAd,
108 IN UCHAR QueIdx, IN PUCHAR pData, IN UINT Length)
110 PNDIS_PACKET pPacket;
111 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
113 UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN];
115 unsigned long IrqFlags = 0;
117 #endif // RTMP_MAC_PCI //
118 BOOLEAN bUseDataQ = FALSE;
121 ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
123 if ((QueIdx & MGMT_USE_QUEUE_FLAG) == MGMT_USE_QUEUE_FLAG) {
125 QueIdx &= (~MGMT_USE_QUEUE_FLAG);
129 IrqState = pAd->irq_disabled;
130 if (pAd->MACVersion == 0x28600100) {
131 QueIdx = (bUseDataQ == TRUE ? QueIdx : 3);
134 if (bUseDataQ && (!IrqState))
135 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
136 #endif // RTMP_MAC_PCI //
139 // Reset is in progress, stop immediately
140 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
142 fRTMP_ADAPTER_HALT_IN_PROGRESS |
143 fRTMP_ADAPTER_NIC_NOT_EXIST)
144 || !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) {
145 Status = NDIS_STATUS_FAILURE;
148 // Check Free priority queue
149 // 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);
157 #endif // RTMP_MAC_PCI //
159 FreeNum = GET_MGMTRING_FREENO(pAd);
163 // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870
164 NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE));
166 RTMPAllocateNdisPacket(pAd, &pPacket,
167 (PUCHAR) & rtmpHwHdr,
168 (TXINFO_SIZE + TXWI_SIZE),
170 if (Status != NDIS_STATUS_SUCCESS) {
171 DBGPRINT(RT_DEBUG_WARN,
172 ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
175 //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
176 //pAd->CommonCfg.MlmeRate = RATE_2;
181 MlmeDataHardTransmit(pAd, QueIdx, pPacket);
184 #endif // RTMP_MAC_PCI //
185 Status = MlmeHardTransmit(pAd, QueIdx, pPacket);
186 if (Status == NDIS_STATUS_SUCCESS)
189 RTMPFreeNdisPacket(pAd, pPacket);
191 pAd->RalinkCounters.MgmtRingFullCount++;
195 DBGPRINT(RT_DEBUG_TRACE,
196 ("retryCnt %d\n", retryCnt));
198 DBGPRINT(RT_DEBUG_ERROR,
199 ("Qidx(%d), not enough space in DataRing, MgmtRingFullCount=%ld!\n",
205 #endif // RTMP_MAC_PCI //
206 DBGPRINT(RT_DEBUG_ERROR,
207 ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n",
209 pAd->RalinkCounters.MgmtRingFullCount));
211 } while (retryCnt > 0);
214 if (bUseDataQ && (!IrqState))
215 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
216 #endif // RTMP_MAC_PCI //
222 ========================================================================
225 Copy frame from waiting queue into relative ring buffer and set
226 appropriate ASIC register to kick hardware transmit function
229 pAd Pointer to our adapter
230 pBuffer Pointer to memory of outgoing frame
231 Length Size of outgoing management frame
239 IRQL = DISPATCH_LEVEL
243 ========================================================================
245 NDIS_STATUS MlmeHardTransmit(IN PRTMP_ADAPTER pAd,
246 IN UCHAR QueIdx, IN PNDIS_PACKET pPacket)
248 PACKET_INFO PacketInfo;
251 PHEADER_802_11 pHeader_802_11;
253 if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
255 return NDIS_STATUS_FAILURE;
258 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
259 if (pSrcBufVA == NULL)
260 return NDIS_STATUS_FAILURE;
262 pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE);
265 if (pAd->MACVersion == 0x28600100)
266 return MlmeHardTransmitTxRing(pAd, QueIdx, pPacket);
268 #endif // RTMP_MAC_PCI //
269 return MlmeHardTransmitMgmtRing(pAd, QueIdx, pPacket);
273 NDIS_STATUS MlmeHardTransmitMgmtRing(IN PRTMP_ADAPTER pAd,
274 IN UCHAR QueIdx, IN PNDIS_PACKET pPacket)
276 PACKET_INFO PacketInfo;
279 PHEADER_802_11 pHeader_802_11;
280 BOOLEAN bAckRequired, bInsertTimestamp;
282 PTXWI_STRUC pFirstTxWI;
283 MAC_TABLE_ENTRY *pMacEntry = NULL;
286 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
288 // Make sure MGMT ring resource won't be used by other threads
289 RTMP_SEM_LOCK(&pAd->MgmtRingLock);
290 if (pSrcBufVA == NULL) {
291 // The buffer shouldn't be NULL
292 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
293 return NDIS_STATUS_FAILURE;
297 // outgoing frame always wakeup PHY to prevent frame lost
298 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
299 AsicForceWakeup(pAd, TRUE);
302 pFirstTxWI = (PTXWI_STRUC) (pSrcBufVA + TXINFO_SIZE);
303 pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); //TXWI_SIZE);
305 if (pHeader_802_11->Addr1[0] & 0x01) {
306 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
308 MlmeRate = pAd->CommonCfg.MlmeRate;
311 // Verify Mlme rate for a / g bands.
312 if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
315 if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
316 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) {
317 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
321 // Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode.
322 if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED
323 || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) {
324 if (pAd->LatchRfRegs.Channel > 14)
325 pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
327 pAd->CommonCfg.MlmeTransmit.field.MODE = 0;
332 // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
333 // Snice it's been set to 0 while on MgtMacHeaderInit
334 // By the way this will cause frame to be send on PWR_SAVE failed.
336 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE; // (pAd->StaCfg.Psm == PWR_SAVE);
339 // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
340 // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
341 // if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL))
343 if ((pHeader_802_11->FC.SubType == SUBTYPE_ACTION) ||
344 ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
345 ((pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL) ||
346 (pHeader_802_11->FC.SubType == SUBTYPE_NULL_FUNC)))) {
347 if (pAd->StaCfg.Psm == PWR_SAVE)
348 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
350 pHeader_802_11->FC.PwrMgmt =
351 pAd->CommonCfg.bAPSDForcePowerSave;
355 bInsertTimestamp = FALSE;
356 if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
358 //Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue.
359 if ((pAd->OpMode == OPMODE_STA)
360 && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL)) {
361 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
363 bAckRequired = FALSE;
364 } else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
367 //pHeader_802_11->Sequence = pAd->Sequence;
369 if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
371 bAckRequired = FALSE;
372 pHeader_802_11->Duration = 0;
375 pHeader_802_11->Duration =
376 RTMPCalcDuration(pAd, MlmeRate, 14);
377 if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
378 && (pHeader_802_11->FC.Type == BTYPE_MGMT)) {
379 bInsertTimestamp = TRUE;
380 bAckRequired = FALSE; // Disable ACK to prevent retry 0x1f for Probe Response
382 if ((pHeader_802_11->FC.SubType ==
384 && (pHeader_802_11->FC.Type == BTYPE_MGMT)) {
385 bAckRequired = FALSE; // Disable ACK to prevent retry 0x1f for Probe Request
390 pHeader_802_11->Sequence = pAd->Sequence++;
391 if (pAd->Sequence > 0xfff)
394 // Before radar detection done, mgmt frame can not be sent but probe req
395 // Because we need to use probe req to trigger driver to send probe req in passive scan
396 if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
397 && (pAd->CommonCfg.bIEEE80211H == 1)
398 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)) {
399 DBGPRINT(RT_DEBUG_ERROR,
400 ("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
402 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
403 return (NDIS_STATUS_FAILURE);
407 // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
408 // should always has only one physical buffer, and the whole frame size equals
409 // to the first scatter buffer size
412 // Initialize TX Descriptor
413 // For inter-frame gap, the number is for this frame and next frame
414 // For MLME rate, we will fix as 2Mb to match other vendor's implement
415 // pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
417 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
420 if (pMacEntry == NULL) {
421 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp,
422 FALSE, bAckRequired, FALSE, 0, RESERVED_WCID,
423 (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID, 0,
424 (UCHAR) pAd->CommonCfg.MlmeTransmit.field.MCS,
425 IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
427 /* dont use low rate to send QoS Null data frame */
428 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
429 bInsertTimestamp, FALSE, bAckRequired, FALSE,
431 (SrcBufLen - TXINFO_SIZE - TXWI_SIZE),
432 pMacEntry->MaxHTPhyMode.field.MCS, 0,
433 (UCHAR) pMacEntry->MaxHTPhyMode.field.MCS,
434 IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
437 // Now do hardware-depened kick out.
438 HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen);
440 // Make sure to release MGMT ring resource
442 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
443 return NDIS_STATUS_SUCCESS;
446 /********************************************************************************
448 New DeQueue Procedures.
450 ********************************************************************************/
452 #define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \
454 if (bIntContext == FALSE) \
455 RTMP_IRQ_LOCK((lock), IrqFlags); \
458 #define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \
460 if (bIntContext == FALSE) \
461 RTMP_IRQ_UNLOCK((lock), IrqFlags); \
465 ========================================================================
466 Tx Path design algorithm:
467 Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal),
468 Specific Packet Type. Following show the classification rule and policy for each kinds of packets.
469 Classification Rule=>
470 Multicast: (*addr1 & 0x01) == 0x01
471 Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc.
472 11N Rate : If peer support HT
473 (1).AMPDU -- If TXBA is negotiated.
474 (2).AMSDU -- If AMSDU is capable for both peer and ourself.
475 *). AMSDU can embedded in a AMPDU, but now we didn't support it.
476 (3).Normal -- Other packets which send as 11n rate.
478 B/G Rate : If peer is b/g only.
479 (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6
480 (2).Normal -- Other packets which send as b/g rate.
482 The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
484 Classified Packet Handle Rule=>
486 No ACK, //pTxBlk->bAckRequired = FALSE;
487 No WMM, //pTxBlk->bWMM = FALSE;
488 No piggyback, //pTxBlk->bPiggyBack = FALSE;
489 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
490 Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use
491 the same policy to handle it.
492 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
495 No piggyback, //pTxBlk->bPiggyBack = FALSE;
507 ========================================================================
509 static UCHAR TxPktClassification(IN RTMP_ADAPTER * pAd, IN PNDIS_PACKET pPacket)
511 UCHAR TxFrameType = TX_UNKOWN_FRAME;
513 MAC_TABLE_ENTRY *pMacEntry = NULL;
514 BOOLEAN bHTRate = FALSE;
516 Wcid = RTMP_GET_PACKET_WCID(pPacket);
517 if (Wcid == MCAST_WCID) { // Handle for RA is Broadcast/Multicast Address.
518 return TX_MCAST_FRAME;
520 // Handle for unicast packets
521 pMacEntry = &pAd->MacTab.Content[Wcid];
522 if (RTMP_GET_PACKET_LOWRATE(pPacket)) { // It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame
523 TxFrameType = TX_LEGACY_FRAME;
524 } else if (IS_HT_RATE(pMacEntry)) { // it's a 11n capable packet
526 // Depends on HTPhyMode to check if the peer support the HTRate transmission.
527 // Currently didn't support A-MSDU embedded in A-MPDU
529 if (RTMP_GET_PACKET_MOREDATA(pPacket)
530 || (pMacEntry->PsMode == PWR_SAVE))
531 TxFrameType = TX_LEGACY_FRAME;
532 else if ((pMacEntry->
533 TXBAbitmap & (1 << (RTMP_GET_PACKET_UP(pPacket)))) !=
535 return TX_AMPDU_FRAME;
536 else if (CLIENT_STATUS_TEST_FLAG
537 (pMacEntry, fCLIENT_STATUS_AMSDU_INUSED))
538 return TX_AMSDU_FRAME;
540 TxFrameType = TX_LEGACY_FRAME;
541 } else { // it's a legacy b/g packet.
542 if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) && (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)))) { // if peer support Ralink Aggregation, we use it.
543 TxFrameType = TX_RALINK_FRAME;
545 TxFrameType = TX_LEGACY_FRAME;
549 // Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU.
550 if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1)
551 && (TxFrameType == TX_LEGACY_FRAME))
552 TxFrameType = TX_FRAG_FRAME;
557 BOOLEAN RTMP_FillTxBlkInfo(IN RTMP_ADAPTER * pAd, IN TX_BLK * pTxBlk)
559 PACKET_INFO PacketInfo;
560 PNDIS_PACKET pPacket;
561 PMAC_TABLE_ENTRY pMacEntry = NULL;
563 pPacket = pTxBlk->pPacket;
564 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader,
567 pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket);
568 pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket);
569 pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket);
570 pTxBlk->FrameGap = IFS_HTTXOP; // ASIC determine Frame Gap
572 if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket))
573 TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame);
575 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame);
577 // Default to clear this flag
578 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS);
580 if (pTxBlk->Wcid == MCAST_WCID) {
581 pTxBlk->pMacEntry = NULL;
584 &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
587 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); // AckRequired = FALSE, when broadcast packet in Adhoc mode.
588 //TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate);
589 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag);
590 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
591 if (RTMP_GET_PACKET_MOREDATA(pPacket)) {
592 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
596 pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
597 pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode;
599 pMacEntry = pTxBlk->pMacEntry;
601 // For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK.
602 if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK)
603 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
605 TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired);
607 if ((pAd->OpMode == OPMODE_STA) &&
609 (RX_FILTER_TEST_FLAG(pAd, fRX_FILTER_ACCEPT_PROMISCUOUS))) {
610 if (pAd->CommonCfg.PSPXlink)
611 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
617 // If support WMM, enable it.
618 if (OPSTATUS_TEST_FLAG
619 (pAd, fOP_STATUS_WMM_INUSED)
620 && CLIENT_STATUS_TEST_FLAG(pMacEntry,
621 fCLIENT_STATUS_WMM_CAPABLE))
622 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM);
624 // if (pAd->StaCfg.bAutoTxRateSwitch)
625 // TX_BLK_SET_FLAG(pTxBlk, fTX_AutoRateSwitch);
629 if (pTxBlk->TxFrameType == TX_LEGACY_FRAME) {
630 if ((RTMP_GET_PACKET_LOWRATE(pPacket)) || ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1))) { // Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate.
632 &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
634 // Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it???
635 if (IS_HT_STA(pTxBlk->pMacEntry) &&
636 (CLIENT_STATUS_TEST_FLAG
637 (pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET))
638 && ((pAd->CommonCfg.bRdg == TRUE)
639 && CLIENT_STATUS_TEST_FLAG(pMacEntry,
640 fCLIENT_STATUS_RDG_CAPABLE)))
642 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
643 TX_BLK_SET_FLAG(pTxBlk,
648 if ((IS_HT_RATE(pMacEntry) == FALSE) && (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE))) { // Currently piggy-back only support when peer is operate in b/g mode.
649 TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack);
652 if (RTMP_GET_PACKET_MOREDATA(pPacket)) {
653 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
655 } else if (pTxBlk->TxFrameType == TX_FRAG_FRAME) {
656 TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag);
659 pMacEntry->DebugTxCount++;
665 BOOLEAN CanDoAggregateTransmit(IN RTMP_ADAPTER * pAd,
666 IN NDIS_PACKET * pPacket, IN TX_BLK * pTxBlk)
669 //DBGPRINT(RT_DEBUG_TRACE, ("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType));
671 if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
674 if (RTMP_GET_PACKET_DHCP(pPacket) ||
675 RTMP_GET_PACKET_EAPOL(pPacket) || RTMP_GET_PACKET_WAI(pPacket))
678 if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) && ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket)) > (RX_BUFFER_AGGRESIZE - 100))) { // For AMSDU, allow the packets with total length < max-amsdu size
682 if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) && (pTxBlk->TxPacketList.Number == 2)) { // For RALINK-Aggregation, allow two frames in one batch.
686 if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP
694 ========================================================================
697 To do the enqueue operation and extract the first item of waiting
698 list. If a number of available shared memory segments could meet
699 the request of extracted item, the extracted item will be fragmented
700 into shared memory segments.
703 pAd Pointer to our adapter
704 pQueue Pointer to Waiting Queue
709 IRQL = DISPATCH_LEVEL
713 ========================================================================
715 VOID RTMPDeQueuePacket(IN PRTMP_ADAPTER pAd, IN BOOLEAN bIntContext, IN UCHAR QIdx, /* BulkOutPipeId */
716 IN UCHAR Max_Tx_Packets)
718 PQUEUE_ENTRY pEntry = NULL;
719 PNDIS_PACKET pPacket;
720 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
722 PQUEUE_HEADER pQueue;
723 ULONG FreeNumber[NUM_OF_TX_RING];
724 UCHAR QueIdx, sQIdx, eQIdx;
725 unsigned long IrqFlags = 0;
726 BOOLEAN hasTxDesc = FALSE;
730 if (QIdx == NUM_OF_TX_RING) {
732 eQIdx = 3; // 4 ACs, start from 0.
734 sQIdx = eQIdx = QIdx;
737 for (QueIdx = sQIdx; QueIdx <= eQIdx; QueIdx++) {
740 RTMP_START_DEQUEUE(pAd, QueIdx, IrqFlags);
745 (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |
746 fRTMP_ADAPTER_RADIO_OFF |
747 fRTMP_ADAPTER_RESET_IN_PROGRESS |
748 fRTMP_ADAPTER_HALT_IN_PROGRESS |
749 fRTMP_ADAPTER_NIC_NOT_EXIST)))) {
750 RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
754 if (Count >= Max_Tx_Packets)
757 DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
758 if (&pAd->TxSwQueue[QueIdx] == NULL) {
759 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext,
764 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
766 if (FreeNumber[QueIdx] <= 5) {
767 // free Tx(QueIdx) resources
768 RTMPFreeTXDUponTxDmaDone(pAd, QueIdx);
770 GET_TXRING_FREENO(pAd, QueIdx);
772 #endif // RTMP_MAC_PCI //
774 // probe the Queue Head
775 pQueue = &pAd->TxSwQueue[QueIdx];
776 if ((pEntry = pQueue->Head) == NULL) {
777 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext,
783 NdisZeroMemory((PUCHAR) pTxBlk, sizeof(TX_BLK));
784 //InitializeQueueHeader(&pTxBlk->TxPacketList); // Didn't need it because we already memzero it.
785 pTxBlk->QueIdx = QueIdx;
787 pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
789 // Early check to make sure we have enoguh Tx Resource.
791 RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk,
795 pAd->PrivateInfo.TxRingFullCnt++;
797 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext,
803 pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
804 pEntry = RemoveHeadQueue(pQueue);
805 pTxBlk->TotalFrameNum++;
806 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
807 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
808 pTxBlk->pPacket = pPacket;
809 InsertTailQueue(&pTxBlk->TxPacketList,
810 PACKET_TO_QUEUE_ENTRY(pPacket));
812 if (pTxBlk->TxFrameType == TX_RALINK_FRAME
813 || pTxBlk->TxFrameType == TX_AMSDU_FRAME) {
814 // Enhance SW Aggregation Mechanism
815 if (NEED_QUEUE_BACK_FOR_AGG
816 (pAd, QueIdx, FreeNumber[QueIdx],
817 pTxBlk->TxFrameType)) {
818 InsertHeadQueue(pQueue,
819 PACKET_TO_QUEUE_ENTRY
821 DEQUEUE_UNLOCK(&pAd->irq_lock,
822 bIntContext, IrqFlags);
827 if ((pEntry = pQueue->Head) == NULL)
830 // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation.
831 pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
833 GET_TXRING_FREENO(pAd, QueIdx);
835 RTMP_HAS_ENOUGH_FREE_DESC(pAd,
840 if ((hasTxDesc == FALSE)
842 (CanDoAggregateTransmit
843 (pAd, pPacket, pTxBlk) == FALSE))
846 //Remove the packet from the TxSwQueue and insert into pTxBlk
847 pEntry = RemoveHeadQueue(pQueue);
849 pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
850 pTxBlk->TotalFrameNum++;
851 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
852 pTxBlk->TotalFrameLen +=
853 GET_OS_PKT_LEN(pPacket);
854 InsertTailQueue(&pTxBlk->TxPacketList,
855 PACKET_TO_QUEUE_ENTRY
859 if (pTxBlk->TxPacketList.Number == 1)
860 pTxBlk->TxFrameType = TX_LEGACY_FRAME;
863 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
864 #endif // RTMP_MAC_USB //
865 Count += pTxBlk->TxPacketList.Number;
867 // Do HardTransmit now.
868 Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
871 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
872 // static rate also need NICUpdateFifoStaCounters() function.
873 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
874 NICUpdateFifoStaCounters(pAd);
875 #endif // RTMP_MAC_PCI //
879 RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
883 RTUSBKickBulkOut(pAd);
884 #endif // RTMP_MAC_USB //
890 ========================================================================
893 Calculates the duration which is required to transmit out frames
894 with given size and specified rate.
897 pAd Pointer to our adapter
899 Size Frame size in units of byte
902 Duration number in units of usec
905 IRQL = DISPATCH_LEVEL
909 ========================================================================
911 USHORT RTMPCalcDuration(IN PRTMP_ADAPTER pAd, IN UCHAR Rate, IN ULONG Size)
915 if (Rate < RATE_FIRST_OFDM_RATE) // CCK
918 && OPSTATUS_TEST_FLAG(pAd,
919 fOP_STATUS_SHORT_PREAMBLE_INUSED))
920 Duration = 96; // 72+24 preamble+plcp
922 Duration = 192; // 144+48 preamble+plcp
924 Duration += (USHORT) ((Size << 4) / RateIdTo500Kbps[Rate]);
925 if ((Size << 4) % RateIdTo500Kbps[Rate])
927 } else if (Rate <= RATE_LAST_OFDM_RATE) // OFDM rates
929 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
931 4 * (USHORT) ((11 + Size * 4) / RateIdTo500Kbps[Rate]);
932 if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
936 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
939 return (USHORT) Duration;
943 ========================================================================
946 Calculates the duration which is required to transmit out frames
947 with given size and specified rate.
950 pTxWI Pointer to head of each MPDU to HW.
951 Ack Setting for Ack requirement bit
952 Fragment Setting for Fragment bit
953 RetryMode Setting for retry mode
954 Ifs Setting for IFS gap
955 Rate Setting for transmit rate
956 Service Setting for service
958 TxPreamble Short or Long preamble when using CCK rates
959 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
965 IRQL = DISPATCH_LEVEL
967 See also : BASmartHardTransmit() !!!
969 ========================================================================
971 VOID RTMPWriteTxWI(IN PRTMP_ADAPTER pAd, IN PTXWI_STRUC pOutTxWI, IN BOOLEAN FRAG, IN BOOLEAN CFACK, IN BOOLEAN InsTimestamp, IN BOOLEAN AMPDU, IN BOOLEAN Ack, IN BOOLEAN NSeq, // HW new a sequence.
979 IN BOOLEAN CfAck, IN HTTRANSMIT_SETTING * pTransmit)
981 PMAC_TABLE_ENTRY pMac = NULL;
985 if (WCID < MAX_LEN_OF_MAC_TABLE)
986 pMac = &pAd->MacTab.Content[WCID];
989 // Always use Long preamble before verifiation short preamble functionality works well.
990 // Todo: remove the following line if short preamble functionality works
992 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
993 NdisZeroMemory(&TxWI, TXWI_SIZE);
998 pTxWI->CFACK = CFACK;
999 pTxWI->TS = InsTimestamp;
1000 pTxWI->AMPDU = AMPDU;
1002 pTxWI->txop = Txopmode;
1005 // John tune the performace with Intel Client in 20 MHz performance
1006 BASize = pAd->CommonCfg.TxBASize;
1007 if (pAd->MACVersion == 0x28720200) {
1014 pTxWI->BAWinSize = BASize;
1015 pTxWI->ShortGI = pTransmit->field.ShortGI;
1016 pTxWI->STBC = pTransmit->field.STBC;
1018 pTxWI->WirelessCliID = WCID;
1019 pTxWI->MPDUtotalByteCount = Length;
1020 pTxWI->PacketId = PID;
1022 // If CCK or OFDM, BW must be 20
1024 (pTransmit->field.MODE <=
1025 MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1027 pTxWI->MCS = pTransmit->field.MCS;
1028 pTxWI->PHYMODE = pTransmit->field.MODE;
1029 pTxWI->CFACK = CfAck;
1032 if (pAd->CommonCfg.bMIMOPSEnable) {
1033 if ((pMac->MmpsMode == MMPS_DYNAMIC)
1034 && (pTransmit->field.MCS > 7)) {
1035 // Dynamic MIMO Power Save Mode
1037 } else if (pMac->MmpsMode == MMPS_STATIC) {
1038 // Static MIMO Power Save Mode
1039 if (pTransmit->field.MODE >= MODE_HTMIX
1040 && pTransmit->field.MCS > 7) {
1046 //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;
1047 if (pMac->bIAmBadAtheros
1048 && (pMac->WepStatus != Ndis802_11WEPDisabled)) {
1049 pTxWI->MpduDensity = 7;
1051 pTxWI->MpduDensity = pMac->MpduDensity;
1055 pTxWI->PacketId = pTxWI->MCS;
1056 NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC));
1059 VOID RTMPWriteTxWI_Data(IN PRTMP_ADAPTER pAd,
1060 IN OUT PTXWI_STRUC pTxWI, IN TX_BLK * pTxBlk)
1062 HTTRANSMIT_SETTING *pTransmit;
1063 PMAC_TABLE_ENTRY pMacEntry;
1068 pTransmit = pTxBlk->pTransmit;
1069 pMacEntry = pTxBlk->pMacEntry;
1072 // Always use Long preamble before verifiation short preamble functionality works well.
1073 // Todo: remove the following line if short preamble functionality works
1075 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1076 NdisZeroMemory(pTxWI, TXWI_SIZE);
1078 pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1079 pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1080 pTxWI->txop = pTxBlk->FrameGap;
1082 pTxWI->WirelessCliID = pTxBlk->Wcid;
1084 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1085 pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
1087 // If CCK or OFDM, BW must be 20
1089 (pTransmit->field.MODE <=
1090 MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1091 pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
1093 // John tune the performace with Intel Client in 20 MHz performance
1094 BASize = pAd->CommonCfg.TxBASize;
1095 if ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry)) {
1096 UCHAR RABAOriIdx = 0; //The RA's BA Originator table index.
1099 pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
1100 BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1103 pTxWI->TxBF = pTransmit->field.TxBF;
1104 pTxWI->BAWinSize = BASize;
1105 pTxWI->ShortGI = pTransmit->field.ShortGI;
1106 pTxWI->STBC = pTransmit->field.STBC;
1108 pTxWI->MCS = pTransmit->field.MCS;
1109 pTxWI->PHYMODE = pTransmit->field.MODE;
1112 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC)
1113 && (pTransmit->field.MCS > 7)) {
1114 // Dynamic MIMO Power Save Mode
1116 } else if (pMacEntry->MmpsMode == MMPS_STATIC) {
1117 // Static MIMO Power Save Mode
1118 if (pTransmit->field.MODE >= MODE_HTMIX
1119 && pTransmit->field.MCS > 7) {
1125 if (pMacEntry->bIAmBadAtheros
1126 && (pMacEntry->WepStatus != Ndis802_11WEPDisabled)) {
1127 pTxWI->MpduDensity = 7;
1129 pTxWI->MpduDensity = pMacEntry->MpduDensity;
1133 // for rate adapation
1134 pTxWI->PacketId = pTxWI->MCS;
1137 VOID RTMPWriteTxWI_Cache(IN PRTMP_ADAPTER pAd,
1138 IN OUT PTXWI_STRUC pTxWI, IN TX_BLK * pTxBlk)
1140 PHTTRANSMIT_SETTING /*pTxHTPhyMode, */ pTransmit;
1141 PMAC_TABLE_ENTRY pMacEntry;
1146 pMacEntry = pTxBlk->pMacEntry;
1147 pTransmit = pTxBlk->pTransmit;
1149 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
1150 //if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pMacEntry))
1151 //if (TX_BLK_TEST_FLAG(pTxBlk, fTX_AutoRateSwitch))
1152 if (pMacEntry->bAutoTxRateSwitch) {
1153 pTxWI->txop = IFS_HTTXOP;
1155 // If CCK or OFDM, BW must be 20
1157 (pTransmit->field.MODE <=
1158 MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1159 pTxWI->ShortGI = pTransmit->field.ShortGI;
1160 pTxWI->STBC = pTransmit->field.STBC;
1162 pTxWI->MCS = pTransmit->field.MCS;
1163 pTxWI->PHYMODE = pTransmit->field.MODE;
1165 // set PID for TxRateSwitching
1166 pTxWI->PacketId = pTransmit->field.MCS;
1169 pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE : FALSE);
1172 if (pAd->CommonCfg.bMIMOPSEnable) {
1173 // MIMO Power Save Mode
1174 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC)
1175 && (pTransmit->field.MCS > 7)) {
1176 // Dynamic MIMO Power Save Mode
1178 } else if (pMacEntry->MmpsMode == MMPS_STATIC) {
1179 // Static MIMO Power Save Mode
1180 if ((pTransmit->field.MODE >= MODE_HTMIX)
1181 && (pTransmit->field.MCS > 7)) {
1188 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1192 // should be called only when -
1193 // 1. MEADIA_CONNECTED
1194 // 2. AGGREGATION_IN_USED
1195 // 3. Fragmentation not in used
1196 // 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible
1197 BOOLEAN TxFrameIsAggregatible(IN PRTMP_ADAPTER pAd,
1198 IN PUCHAR pPrevAddr1, IN PUCHAR p8023hdr)
1201 // can't aggregate EAPOL (802.1x) frame
1202 if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1205 // can't aggregate multicast/broadcast frame
1206 if (p8023hdr[0] & 0x01)
1209 if (INFRA_ON(pAd)) // must be unicast to AP
1211 else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA
1218 ========================================================================
1220 Routine Description:
1221 Check the MSDU Aggregation policy
1222 1.HT aggregation is A-MSDU
1223 2.legaacy rate aggregation is software aggregation by Ralink.
1231 ========================================================================
1233 BOOLEAN PeerIsAggreOn(IN PRTMP_ADAPTER pAd,
1234 IN ULONG TxRate, IN PMAC_TABLE_ENTRY pMacEntry)
1237 (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
1239 if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags)) {
1240 if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) {
1243 #ifdef AGGREGATION_SUPPORT
1244 if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)))) { // legacy Ralink Aggregation support
1247 #endif // AGGREGATION_SUPPORT //
1255 ========================================================================
1257 Routine Description:
1258 Check and fine the packet waiting in SW queue with highest priority
1261 pAd Pointer to our adapter
1264 pQueue Pointer to Waiting Queue
1266 IRQL = DISPATCH_LEVEL
1270 ========================================================================
1272 PQUEUE_HEADER RTMPCheckTxSwQueue(IN PRTMP_ADAPTER pAd, OUT PUCHAR pQueIdx)
1276 // 2004-11-15 to be removed. test aggregation only
1277 // if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2))
1280 Number = pAd->TxSwQueue[QID_AC_BK].Number
1281 + pAd->TxSwQueue[QID_AC_BE].Number
1282 + pAd->TxSwQueue[QID_AC_VI].Number
1283 + pAd->TxSwQueue[QID_AC_VO].Number;
1285 if (pAd->TxSwQueue[QID_AC_VO].Head != NULL) {
1286 *pQueIdx = QID_AC_VO;
1287 return (&pAd->TxSwQueue[QID_AC_VO]);
1288 } else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL) {
1289 *pQueIdx = QID_AC_VI;
1290 return (&pAd->TxSwQueue[QID_AC_VI]);
1291 } else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL) {
1292 *pQueIdx = QID_AC_BE;
1293 return (&pAd->TxSwQueue[QID_AC_BE]);
1294 } else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL) {
1295 *pQueIdx = QID_AC_BK;
1296 return (&pAd->TxSwQueue[QID_AC_BK]);
1298 // No packet pending in Tx Sw queue
1299 *pQueIdx = QID_AC_BK;
1305 ========================================================================
1307 Routine Description:
1308 Suspend MSDU transmission
1311 pAd Pointer to our adapter
1318 ========================================================================
1320 VOID RTMPSuspendMsduTransmission(IN PRTMP_ADAPTER pAd)
1322 DBGPRINT(RT_DEBUG_TRACE, ("SCANNING, suspend MSDU transmission ...\n"));
1325 // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
1326 // use Lowbound as R66 value on ScanNextChannel(...)
1328 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66,
1329 &pAd->BbpTuning.R66CurrentValue);
1331 // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)
1332 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd)));
1333 RTMPSetAGCInitValue(pAd, BW_20);
1335 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1336 //RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000); // abort all TX rings
1340 ========================================================================
1342 Routine Description:
1343 Resume MSDU transmission
1346 pAd Pointer to our adapter
1351 IRQL = DISPATCH_LEVEL
1355 ========================================================================
1357 VOID RTMPResumeMsduTransmission(IN PRTMP_ADAPTER pAd)
1361 DBGPRINT(RT_DEBUG_TRACE, ("SCAN done, resume MSDU transmission ...\n"));
1363 // After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value
1364 // R66 should not be 0
1365 if (pAd->BbpTuning.R66CurrentValue == 0) {
1366 pAd->BbpTuning.R66CurrentValue = 0x38;
1367 DBGPRINT_ERR(("RTMPResumeMsduTransmission, R66CurrentValue=0...\n"));
1370 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66,
1371 pAd->BbpTuning.R66CurrentValue);
1373 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1374 // sample, for IRQ LOCK to SEM LOCK
1375 // IrqState = pAd->irq_disabled;
1377 // RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1379 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1382 UINT deaggregate_AMSDU_announce(IN PRTMP_ADAPTER pAd,
1383 PNDIS_PACKET pPacket,
1384 IN PUCHAR pData, IN ULONG DataSize)
1387 USHORT SubFrameSize;
1388 PHEADER_802_3 pAMSDUsubheader;
1390 UCHAR Header802_3[14];
1392 PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP;
1393 PNDIS_PACKET pClonePacket;
1397 while (DataSize > LENGTH_802_3) {
1401 //hex_dump("subheader", pData, 64);
1402 pAMSDUsubheader = (PHEADER_802_3) pData;
1403 //pData += LENGTH_802_3;
1405 pAMSDUsubheader->Octet[1] +
1406 (pAMSDUsubheader->Octet[0] << 8);
1407 SubFrameSize = PayloadSize + LENGTH_802_3;
1409 if ((DataSize < SubFrameSize) || (PayloadSize > 1518)) {
1412 //DBGPRINT(RT_DEBUG_TRACE,("%d subframe: Size = %d\n", nMSDU, PayloadSize));
1414 pPayload = pData + LENGTH_802_3;
1416 pSA = pData + MAC_ADDR_LEN;
1418 // convert to 802.3 header
1419 CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize,
1422 if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E)) {
1423 /* avoid local heap overflow, use dyanamic allocation */
1424 MLME_QUEUE_ELEM *Elem =
1425 (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM),
1429 (LENGTH_802_11 + LENGTH_802_1_H),
1430 pPayload, PayloadSize);
1432 LENGTH_802_11 + LENGTH_802_1_H +
1434 //WpaEAPOLKeyAction(pAd, Elem);
1435 REPORT_MGMT_FRAME_TO_MLME(pAd, BSSID_WCID,
1437 Elem->MsgLen, 0, 0, 0,
1444 if (pRemovedLLCSNAP) {
1445 pPayload -= LENGTH_802_3;
1446 PayloadSize += LENGTH_802_3;
1447 NdisMoveMemory(pPayload, &Header802_3[0],
1452 pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
1454 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket,
1459 // A-MSDU has padding to multiple of 4 including subframe header.
1460 // align SubFrameSize up to multiple of 4
1461 SubFrameSize = (SubFrameSize + 3) & (~0x3);
1463 if (SubFrameSize > 1528 || SubFrameSize < 32) {
1467 if (DataSize > SubFrameSize) {
1468 pData += SubFrameSize;
1469 DataSize -= SubFrameSize;
1476 // finally release original rx packet
1477 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1482 UINT BA_Reorder_AMSDU_Annnounce(IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPacket)
1488 pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
1489 DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
1491 nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
1497 ==========================================================================
1499 Look up the MAC address in the MAC table. Return NULL if not found.
1501 pEntry - pointer to the MAC entry; NULL is not found
1502 ==========================================================================
1504 MAC_TABLE_ENTRY *MacTableLookup(IN PRTMP_ADAPTER pAd, PUCHAR pAddr)
1507 MAC_TABLE_ENTRY *pEntry = NULL;
1509 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1510 pEntry = pAd->MacTab.Hash[HashIdx];
1513 && (pEntry->ValidAsCLI || pEntry->ValidAsWDS
1514 || pEntry->ValidAsApCli || pEntry->ValidAsMesh)) {
1515 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) {
1518 pEntry = pEntry->pNext;
1524 MAC_TABLE_ENTRY *MacTableInsertEntry(IN PRTMP_ADAPTER pAd,
1526 IN UCHAR apidx, IN BOOLEAN CleanAll)
1530 MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
1535 if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
1540 if (pAd->StaCfg.BssType == BSS_INFRA)
1543 // allocate one MAC entry
1544 NdisAcquireSpinLock(&pAd->MacTabLock);
1545 for (i = FirstWcid; i < MAX_LEN_OF_MAC_TABLE; i++) // skip entry#0 so that "entry index == AID" for fast lookup
1547 // pick up the first available vacancy
1548 if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
1549 (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
1550 (pAd->MacTab.Content[i].ValidAsApCli == FALSE) &&
1551 (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
1553 pEntry = &pAd->MacTab.Content[i];
1554 if (CleanAll == TRUE) {
1555 pEntry->MaxSupportedRate = RATE_11;
1556 pEntry->CurrTxRate = RATE_11;
1557 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1558 pEntry->PairwiseKey.KeyLen = 0;
1559 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1563 pEntry->ValidAsCLI = TRUE;
1564 pEntry->ValidAsWDS = FALSE;
1565 pEntry->ValidAsApCli = FALSE;
1566 pEntry->ValidAsMesh = FALSE;
1567 pEntry->ValidAsDls = FALSE;
1571 pEntry->bIAmBadAtheros = FALSE;
1573 pEntry->CMTimerRunning = FALSE;
1574 pEntry->EnqueueEapolStartTimerRunning =
1575 EAPOL_START_DISABLE;
1576 pEntry->RSNIE_Len = 0;
1577 NdisZeroMemory(pEntry->R_Counter,
1578 sizeof(pEntry->R_Counter));
1579 pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
1581 if (pEntry->ValidAsMesh)
1583 (apidx - MIN_NET_DEVICE_FOR_MESH);
1584 else if (pEntry->ValidAsApCli)
1586 (apidx - MIN_NET_DEVICE_FOR_APCLI);
1587 else if (pEntry->ValidAsWDS)
1589 (apidx - MIN_NET_DEVICE_FOR_WDS);
1591 pEntry->apidx = apidx;
1595 pEntry->AuthMode = pAd->StaCfg.AuthMode;
1597 pAd->StaCfg.WepStatus;
1598 pEntry->PrivacyFilter =
1599 Ndis802_11PrivFilterAcceptAll;
1601 AsicRemovePairwiseKeyEntry(pAd,
1605 #endif // RTMP_MAC_PCI //
1609 pEntry->GTKState = REKEY_NEGOTIATING;
1610 pEntry->PairwiseKey.KeyLen = 0;
1611 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1612 pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
1614 pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
1615 COPY_MAC_ADDR(pEntry->Addr, pAddr);
1616 pEntry->Sst = SST_NOT_AUTH;
1617 pEntry->AuthState = AS_NOT_AUTH;
1618 pEntry->Aid = (USHORT) i; //0;
1619 pEntry->CapabilityInfo = 0;
1620 pEntry->PsMode = PWR_ACTIVE;
1621 pEntry->PsQIdleCount = 0;
1622 pEntry->NoDataIdleCount = 0;
1623 pEntry->AssocDeadLine = MAC_TABLE_ASSOC_TIMEOUT;
1624 pEntry->ContinueTxFailCnt = 0;
1625 InitializeQueueHeader(&pEntry->PsQueue);
1628 // Add this entry into ASIC RX WCID search table
1629 RTMP_STA_ENTRY_ADD(pAd, pEntry);
1631 DBGPRINT(RT_DEBUG_TRACE,
1632 ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",
1633 i, pAd->MacTab.Size));
1638 // add this MAC entry into HASH table
1640 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1641 if (pAd->MacTab.Hash[HashIdx] == NULL) {
1642 pAd->MacTab.Hash[HashIdx] = pEntry;
1644 pCurrEntry = pAd->MacTab.Hash[HashIdx];
1645 while (pCurrEntry->pNext != NULL)
1646 pCurrEntry = pCurrEntry->pNext;
1647 pCurrEntry->pNext = pEntry;
1651 NdisReleaseSpinLock(&pAd->MacTabLock);
1656 ==========================================================================
1658 Delete a specified client from MAC table
1659 ==========================================================================
1661 BOOLEAN MacTableDeleteEntry(IN PRTMP_ADAPTER pAd,
1662 IN USHORT wcid, IN PUCHAR pAddr)
1665 MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
1667 //USHORT offset; // unused variable
1668 //UCHAR j; // unused variable
1670 if (wcid >= MAX_LEN_OF_MAC_TABLE)
1673 NdisAcquireSpinLock(&pAd->MacTabLock);
1675 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1676 //pEntry = pAd->MacTab.Hash[HashIdx];
1677 pEntry = &pAd->MacTab.Content[wcid];
1680 && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS
1681 || pEntry->ValidAsMesh)) {
1682 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) {
1684 // Delete this entry from ASIC on-chip WCID Table
1685 RTMP_STA_ENTRY_MAC_RESET(pAd, wcid);
1687 // free resources of BA
1688 BASessionTearDownALL(pAd, pEntry->Aid);
1691 pProbeEntry = pAd->MacTab.Hash[HashIdx];
1692 ASSERT(pProbeEntry);
1696 if (pProbeEntry == pEntry) {
1697 if (pPrevEntry == NULL) {
1698 pAd->MacTab.Hash[HashIdx] =
1707 pPrevEntry = pProbeEntry;
1708 pProbeEntry = pProbeEntry->pNext;
1709 } while (pProbeEntry);
1712 ASSERT(pProbeEntry != NULL);
1714 RTMP_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
1716 if (pEntry->EnqueueEapolStartTimerRunning !=
1717 EAPOL_START_DISABLE) {
1718 RTMPCancelTimer(&pEntry->
1719 EnqueueStartForPSKTimer,
1721 pEntry->EnqueueEapolStartTimerRunning =
1722 EAPOL_START_DISABLE;
1725 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1727 DBGPRINT(RT_DEBUG_TRACE,
1728 ("MacTableDeleteEntry1 - Total= %d\n",
1731 DBGPRINT(RT_DEBUG_OFF,
1732 ("\n%s: Impossible Wcid = %d !!!!!\n",
1737 NdisReleaseSpinLock(&pAd->MacTabLock);
1739 //Reset operating mode when no Sta.
1740 if (pAd->MacTab.Size == 0) {
1741 pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
1742 //AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/);
1743 RTMP_UPDATE_PROTECT(pAd); // edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet
1750 ==========================================================================
1752 This routine reset the entire MAC table. All packets pending in
1753 the power-saving queues are freed here.
1754 ==========================================================================
1756 VOID MacTableReset(IN PRTMP_ADAPTER pAd)
1760 DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
1761 //NdisAcquireSpinLock(&pAd->MacTabLock);
1763 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
1765 RTMP_STA_ENTRY_MAC_RESET(pAd, i);
1766 #endif // RTMP_MAC_PCI //
1767 if (pAd->MacTab.Content[i].ValidAsCLI == TRUE) {
1769 // free resources of BA
1770 BASessionTearDownALL(pAd, i);
1772 pAd->MacTab.Content[i].ValidAsCLI = FALSE;
1775 NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6);
1776 RTMP_STA_ENTRY_MAC_RESET(pAd, i);
1777 #endif // RTMP_MAC_USB //
1779 //AsicDelWcidTab(pAd, i);
1787 ==========================================================================
1790 IRQL = DISPATCH_LEVEL
1792 ==========================================================================
1794 VOID AssocParmFill(IN PRTMP_ADAPTER pAd,
1795 IN OUT MLME_ASSOC_REQ_STRUCT * AssocReq,
1797 IN USHORT CapabilityInfo,
1798 IN ULONG Timeout, IN USHORT ListenIntv)
1800 COPY_MAC_ADDR(AssocReq->Addr, pAddr);
1801 // Add mask to support 802.11b mode only
1802 AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request
1803 AssocReq->Timeout = Timeout;
1804 AssocReq->ListenIntv = ListenIntv;
1808 ==========================================================================
1811 IRQL = DISPATCH_LEVEL
1813 ==========================================================================
1815 VOID DisassocParmFill(IN PRTMP_ADAPTER pAd,
1816 IN OUT MLME_DISASSOC_REQ_STRUCT * DisassocReq,
1817 IN PUCHAR pAddr, IN USHORT Reason)
1819 COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
1820 DisassocReq->Reason = Reason;
1824 ========================================================================
1826 Routine Description:
1827 Check the out going frame, if this is an DHCP or ARP datagram
1828 will be duplicate another frame at low data rate transmit.
1831 pAd Pointer to our adapter
1832 pPacket Pointer to outgoing Ndis frame
1835 TRUE To be duplicate at Low data rate transmit. (1mb)
1838 IRQL = DISPATCH_LEVEL
1842 MAC header + IP Header + UDP Header
1846 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
1848 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
1851 port 0x43 means Bootstrap Protocol, server.
1852 Port 0x44 means Bootstrap Protocol, client.
1854 ========================================================================
1857 BOOLEAN RTMPCheckDHCPFrame(IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPacket)
1859 PACKET_INFO PacketInfo;
1860 ULONG NumberOfBytesRead = 0;
1861 ULONG CurrentOffset = 0;
1862 PVOID pVirtualAddress = NULL;
1863 UINT NdisBufferLength;
1866 UCHAR ByteOffset36 = 0;
1867 UCHAR ByteOffset38 = 0;
1868 BOOLEAN ReadFirstParm = TRUE;
1870 RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *) & pVirtualAddress,
1873 NumberOfBytesRead += NdisBufferLength;
1874 pSrc = (PUCHAR) pVirtualAddress;
1875 Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
1878 // Check DHCP & BOOTP protocol
1880 while (NumberOfBytesRead <= PacketInfo.TotalPacketLength) {
1881 if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE)) {
1883 35 - (NumberOfBytesRead - NdisBufferLength);
1884 ByteOffset36 = *(pSrc + CurrentOffset);
1885 ReadFirstParm = FALSE;
1888 if (NumberOfBytesRead >= 37) {
1890 37 - (NumberOfBytesRead - NdisBufferLength);
1891 ByteOffset38 = *(pSrc + CurrentOffset);
1898 // Check for DHCP & BOOTP protocol
1899 if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43)) {
1901 // 2054 (hex 0806) for ARP datagrams
1902 // if this packet is not ARP datagrams, then do nothing
1903 // ARP datagrams will also be duplicate at 1mb broadcast frames
1905 if (Protocol != 0x0806)
1912 BOOLEAN RTMPCheckEtherType(IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPacket)
1918 UINT16 srcPort, dstPort;
1919 BOOLEAN status = TRUE;
1921 pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
1922 pktLen = GET_OS_PKT_LEN(pPacket);
1926 RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
1928 // get Ethernet protocol field
1929 TypeLen = (pSrcBuf[12] << 8) | pSrcBuf[13];
1931 pSrcBuf += LENGTH_802_3; // Skip the Ethernet Header.
1933 if (TypeLen <= 1500) { // 802.3, 802.3 LLC
1935 DestMAC(6) + SrcMAC(6) + Lenght(2) +
1936 DSAP(1) + SSAP(1) + Control(1) +
1937 if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
1938 => + SNAP (5, OriginationID(3) + etherType(2))
1940 if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA
1941 && pSrcBuf[2] == 0x03) {
1942 Sniff2BytesFromNdisBuffer((PNDIS_BUFFER) pSrcBuf, 6,
1944 RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
1945 TypeLen = (USHORT) ((Byte0 << 8) + Byte1);
1946 pSrcBuf += 8; // Skip this LLC/SNAP header
1948 //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.
1951 // If it's a VLAN packet, get the real Type/Length field.
1952 if (TypeLen == 0x8100) {
1953 /* 0x8100 means VLAN packets */
1955 /* Dest. MAC Address (6-bytes) +
1956 Source MAC Address (6-bytes) +
1957 Length/Type = 802.1Q Tag Type (2-byte) +
1958 Tag Control Information (2-bytes) +
1959 Length / Type (2-bytes) +
1960 data payload (0-n bytes) +
1962 Frame Check Sequence (4-bytes) */
1964 RTMP_SET_PACKET_VLAN(pPacket, 1);
1965 Sniff2BytesFromNdisBuffer((PNDIS_BUFFER) pSrcBuf, 2, &Byte0,
1967 TypeLen = (USHORT) ((Byte0 << 8) + Byte1);
1969 pSrcBuf += 4; // Skip the VLAN Header.
1975 ASSERT((pktLen > 34));
1976 if (*(pSrcBuf + 9) == 0x11) { // udp packet
1977 ASSERT((pktLen > 34)); // 14 for ethernet header, 20 for IP header
1979 pSrcBuf += 20; // Skip the IP header
1981 OS_NTOHS(get_unaligned
1982 ((PUINT16) (pSrcBuf)));
1984 OS_NTOHS(get_unaligned
1985 ((PUINT16) (pSrcBuf + 2)));
1987 if ((srcPort == 0x44 && dstPort == 0x43) || (srcPort == 0x43 && dstPort == 0x44)) { //It's a BOOTP/DHCP packet
1988 RTMP_SET_PACKET_DHCP(pPacket, 1);
1996 RTMP_SET_PACKET_DHCP(pPacket, 1);
2002 RTMP_SET_PACKET_EAPOL(pPacket, 1);
2014 VOID Update_Rssi_Sample(IN PRTMP_ADAPTER pAd,
2015 IN RSSI_SAMPLE * pRssi, IN PRXWI_STRUC pRxWI)
2017 CHAR rssi0 = pRxWI->RSSI0;
2018 CHAR rssi1 = pRxWI->RSSI1;
2019 CHAR rssi2 = pRxWI->RSSI2;
2022 pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR) rssi0, RSSI_0);
2024 (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
2025 pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
2029 pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR) rssi1, RSSI_1);
2031 (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
2032 pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
2036 pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR) rssi2, RSSI_2);
2038 (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
2039 pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
2043 // Normal legacy Rx packet indication
2044 VOID Indicate_Legacy_Packet(IN PRTMP_ADAPTER pAd,
2045 IN RX_BLK * pRxBlk, IN UCHAR FromWhichBSSID)
2047 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2048 UCHAR Header802_3[LENGTH_802_3];
2050 // 1. get 802.3 Header
2052 // a. pointer pRxBlk->pData to payload
2053 // b. modify pRxBlk->DataSize
2054 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2056 if (pRxBlk->DataSize > MAX_RX_PKT_LEN) {
2059 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2063 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
2066 if (pAd->CommonCfg.bDisableReordering == 0) {
2067 PBA_REC_ENTRY pBAEntry;
2069 UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID;
2070 UCHAR TID = pRxBlk->pRxWI->TID;
2073 #define REORDERING_PACKET_TIMEOUT ((100 * OS_HZ)/1000) // system ticks -- 100 ms
2075 if (Wcid < MAX_LEN_OF_MAC_TABLE) {
2076 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
2078 pBAEntry = &pAd->BATable.BARecEntry[Idx];
2079 // update last rx time
2080 NdisGetSystemUpTime(&Now32);
2081 if ((pBAEntry->list.qlen > 0) &&
2082 RTMP_TIME_AFTER((unsigned long)Now32,
2083 (unsigned long)(pBAEntry->
2086 (REORDERING_PACKET_TIMEOUT)))
2088 DBGPRINT(RT_DEBUG_OFF,
2089 ("Indicate_Legacy_Packet():flush reordering_timeout_mpdus! RxWI->Flags=%d, pRxWI.TID=%d, RxD->AMPDU=%d!\n",
2092 pRxBlk->RxD.AMPDU));
2093 hex_dump("Dump the legacy Packet:",
2094 GET_OS_PKT_DATAPTR(pRxBlk->
2097 ba_flush_reordering_timeout_mpdus(pAd,
2104 #endif // RTMP_MAC_USB //
2106 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2109 // pass this 802.3 packet to upper layer or forward this packet to WM directly
2111 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
2114 // Normal, AMPDU or AMSDU
2115 VOID CmmRxnonRalinkFrameIndicate(IN PRTMP_ADAPTER pAd,
2116 IN RX_BLK * pRxBlk, IN UCHAR FromWhichBSSID)
2118 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU)
2119 && (pAd->CommonCfg.bDisableReordering == 0)) {
2120 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2122 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) {
2124 Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2126 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
2131 VOID CmmRxRalinkFrameIndicate(IN PRTMP_ADAPTER pAd,
2132 IN MAC_TABLE_ENTRY * pEntry,
2133 IN RX_BLK * pRxBlk, IN UCHAR FromWhichBSSID)
2135 UCHAR Header802_3[LENGTH_802_3];
2137 UINT16 Payload1Size, Payload2Size;
2139 PNDIS_PACKET pPacket2 = NULL;
2141 Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData + 1) << 8);
2143 if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize)) {
2144 /* skip two byte MSDU2 len */
2146 pRxBlk->DataSize -= 2;
2149 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
2150 NDIS_STATUS_FAILURE);
2154 // get 802.3 Header and remove LLC
2155 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2157 ASSERT(pRxBlk->pRxPacket);
2159 // Ralink Aggregation frame
2160 pAd->RalinkCounters.OneSecRxAggregationCount++;
2161 Payload1Size = pRxBlk->DataSize - Msdu2Size;
2162 Payload2Size = Msdu2Size - LENGTH_802_3;
2164 pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
2167 duplicate_pkt(pAd, (pData2 - LENGTH_802_3), LENGTH_802_3, pData2,
2168 Payload2Size, FromWhichBSSID);
2172 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
2173 NDIS_STATUS_FAILURE);
2176 // update payload size of 1st packet
2177 pRxBlk->DataSize = Payload1Size;
2178 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2180 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket,
2184 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
2188 #define RESET_FRAGFRAME(_fragFrame) \
2190 _fragFrame.RxSize = 0; \
2191 _fragFrame.Sequence = 0; \
2192 _fragFrame.LastFrag = 0; \
2193 _fragFrame.Flags = 0; \
2196 PNDIS_PACKET RTMPDeFragmentDataFrame(IN PRTMP_ADAPTER pAd, IN RX_BLK * pRxBlk)
2198 PHEADER_802_11 pHeader = pRxBlk->pHeader;
2199 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2200 UCHAR *pData = pRxBlk->pData;
2201 USHORT DataSize = pRxBlk->DataSize;
2202 PNDIS_PACKET pRetPacket = NULL;
2203 UCHAR *pFragBuffer = NULL;
2204 BOOLEAN bReassDone = FALSE;
2205 UCHAR HeaderRoom = 0;
2209 HeaderRoom = pData - (UCHAR *) pHeader;
2211 // Re-assemble the fragmented packets
2212 if (pHeader->Frag == 0) // Frag. Number is 0 : First frag or only one pkt
2214 // the first pkt of fragment, record it.
2215 if (pHeader->FC.MoreFrag) {
2216 ASSERT(pAd->FragFrame.pFragPacket);
2218 GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2219 pAd->FragFrame.RxSize = DataSize + HeaderRoom;
2220 NdisMoveMemory(pFragBuffer, pHeader,
2221 pAd->FragFrame.RxSize);
2222 pAd->FragFrame.Sequence = pHeader->Sequence;
2223 pAd->FragFrame.LastFrag = pHeader->Frag; // Should be 0
2224 ASSERT(pAd->FragFrame.LastFrag == 0);
2225 goto done; // end of processing this frame
2227 } else //Middle & End of fragment
2229 if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
2230 (pHeader->Frag != (pAd->FragFrame.LastFrag + 1))) {
2231 // Fragment is not the same sequence or out of fragment number order
2232 // Reset Fragment control blk
2233 RESET_FRAGFRAME(pAd->FragFrame);
2234 DBGPRINT(RT_DEBUG_ERROR,
2235 ("Fragment is not the same sequence or out of fragment number order.\n"));
2236 goto done; // give up this frame
2237 } else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE) {
2238 // Fragment frame is too large, it exeeds the maximum frame size.
2239 // Reset Fragment control blk
2240 RESET_FRAGFRAME(pAd->FragFrame);
2241 DBGPRINT(RT_DEBUG_ERROR,
2242 ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
2243 goto done; // give up this frame
2246 // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.
2247 // In this case, we will dropt it.
2249 if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H))) {
2250 DBGPRINT(RT_DEBUG_ERROR,
2251 ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n",
2252 pHeader->Sequence, pHeader->Frag));
2253 goto done; // give up this frame
2256 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2258 // concatenate this fragment into the re-assembly buffer
2259 NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData,
2261 pAd->FragFrame.RxSize += DataSize;
2262 pAd->FragFrame.LastFrag = pHeader->Frag; // Update fragment number
2265 if (pHeader->FC.MoreFrag == FALSE) {
2271 // always release rx fragmented packet
2272 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2274 // return defragmented packet if packet is reassembled completely
2275 // otherwise return NULL
2277 PNDIS_PACKET pNewFragPacket;
2279 // allocate a new packet buffer for fragment
2281 RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
2282 if (pNewFragPacket) {
2284 pRetPacket = pAd->FragFrame.pFragPacket;
2285 pAd->FragFrame.pFragPacket = pNewFragPacket;
2287 (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
2288 pRxBlk->pData = (UCHAR *) pRxBlk->pHeader + HeaderRoom;
2289 pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
2290 pRxBlk->pRxPacket = pRetPacket;
2292 RESET_FRAGFRAME(pAd->FragFrame);
2299 VOID Indicate_AMSDU_Packet(IN PRTMP_ADAPTER pAd,
2300 IN RX_BLK * pRxBlk, IN UCHAR FromWhichBSSID)
2304 update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
2305 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
2307 deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData,
2311 VOID Indicate_EAPOL_Packet(IN PRTMP_ADAPTER pAd,
2312 IN RX_BLK * pRxBlk, IN UCHAR FromWhichBSSID)
2314 MAC_TABLE_ENTRY *pEntry = NULL;
2317 pEntry = &pAd->MacTab.Content[BSSID_WCID];
2318 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
2322 if (pEntry == NULL) {
2323 DBGPRINT(RT_DEBUG_WARN,
2324 ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
2326 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
2327 NDIS_STATUS_FAILURE);
2332 #define BCN_TBTT_OFFSET 64 //defer 64 us
2333 VOID ReSyncBeaconTime(IN PRTMP_ADAPTER pAd)
2338 Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
2340 pAd->TbttTickCount++;
2343 // The updated BeaconInterval Value will affect Beacon Interval after two TBTT
2344 // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
2346 if (Offset == (BCN_TBTT_OFFSET - 2)) {
2347 BCN_TIME_CFG_STRUC csr;
2348 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2349 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1; // ASIC register in units of 1/16 TU = 64us
2350 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2352 if (Offset == (BCN_TBTT_OFFSET - 1)) {
2353 BCN_TIME_CFG_STRUC csr;
2355 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2356 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU
2357 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);