2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 *************************************************************************
28 #include "../rt_config.h"
30 #define MAX_TX_IN_TBTT (16)
33 UCHAR SNAP_802_1H[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
34 UCHAR SNAP_BRIDGE_TUNNEL[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8};
35 // Add Cisco Aironet SNAP heade for CCX2 support
36 UCHAR SNAP_AIRONET[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00};
37 UCHAR CKIP_LLC_SNAP[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02};
38 UCHAR EAPOL_LLC_SNAP[]= {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e};
39 UCHAR EAPOL[] = {0x88, 0x8e};
40 UCHAR TPID[] = {0x81, 0x00}; /* VLAN related */
42 UCHAR IPX[] = {0x81, 0x37};
43 UCHAR APPLE_TALK[] = {0x80, 0xf3};
44 UCHAR RateIdToPlcpSignal[12] = {
45 0, /* RATE_1 */ 1, /* RATE_2 */ 2, /* RATE_5_5 */ 3, /* RATE_11 */ // see BBP spec
46 11, /* RATE_6 */ 15, /* RATE_9 */ 10, /* RATE_12 */ 14, /* RATE_18 */ // see IEEE802.11a-1999 p.14
47 9, /* RATE_24 */ 13, /* RATE_36 */ 8, /* RATE_48 */ 12 /* RATE_54 */ }; // see IEEE802.11a-1999 p.14
49 UCHAR OfdmSignalToRateId[16] = {
50 RATE_54, RATE_54, RATE_54, RATE_54, // OFDM PLCP Signal = 0, 1, 2, 3 respectively
51 RATE_54, RATE_54, RATE_54, RATE_54, // OFDM PLCP Signal = 4, 5, 6, 7 respectively
52 RATE_48, RATE_24, RATE_12, RATE_6, // OFDM PLCP Signal = 8, 9, 10, 11 respectively
53 RATE_54, RATE_36, RATE_18, RATE_9, // OFDM PLCP Signal = 12, 13, 14, 15 respectively
56 UCHAR OfdmRateToRxwiMCS[12] = {
58 0, 1, 2, 3, // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3
59 4, 5, 6, 7, // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7
61 UCHAR RxwiMCSToOfdmRate[12] = {
62 RATE_6, RATE_9, RATE_12, RATE_18,
63 RATE_24, RATE_36, RATE_48, RATE_54, // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3
64 4, 5, 6, 7, // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7
67 char* MCSToMbps[] = {"1Mbps","2Mbps","5.5Mbps","11Mbps","06Mbps","09Mbps","12Mbps","18Mbps","24Mbps","36Mbps","48Mbps","54Mbps","MM-0","MM-1","MM-2","MM-3","MM-4","MM-5","MM-6","MM-7","MM-8","MM-9","MM-10","MM-11","MM-12","MM-13","MM-14","MM-15","MM-32","ee1","ee2","ee3"};
69 UCHAR default_cwmin[]={CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1, CW_MIN_IN_BITS-2};
70 UCHAR default_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;
109 UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN];
111 ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
117 IrqState = pAd->irq_disabled;
121 // Reset is in progress, stop immediately
122 if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
123 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)||
124 !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
126 Status = NDIS_STATUS_FAILURE;
130 // Check Free priority queue
131 // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing.
134 if (pAd->MACVersion == 0x28600100)
136 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
140 FreeNum = GET_MGMTRING_FREENO(pAd);
145 // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870
146 NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE));
147 Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE), pData, Length);
148 if (Status != NDIS_STATUS_SUCCESS)
150 DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
154 //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
155 //pAd->CommonCfg.MlmeRate = RATE_2;
158 Status = MlmeHardTransmit(pAd, QueIdx, pPacket);
159 if (Status != NDIS_STATUS_SUCCESS)
160 RTMPFreeNdisPacket(pAd, pPacket);
164 pAd->RalinkCounters.MgmtRingFullCount++;
165 DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n",
166 QueIdx, pAd->RalinkCounters.MgmtRingFullCount));
177 NDIS_STATUS MlmeDataHardTransmit(
178 IN PRTMP_ADAPTER pAd,
180 IN PNDIS_PACKET pPacket);
182 #define MAX_DATAMM_RETRY 3
184 ========================================================================
187 API for MLME to transmit management frame to AP (BSS Mode)
188 or station (IBSS Mode)
191 pAd Pointer to our adapter
192 pData Pointer to the outgoing 802.11 frame
193 Length Size of outgoing management frame
201 IRQL = DISPATCH_LEVEL
205 ========================================================================
207 NDIS_STATUS MiniportDataMMRequest(
208 IN PRTMP_ADAPTER pAd,
213 PNDIS_PACKET pPacket;
214 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
218 UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN];
220 ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
223 IrqState = pAd->irq_disabled;
227 // Reset is in progress, stop immediately
228 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
229 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)||
230 !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
232 Status = NDIS_STATUS_FAILURE;
236 // Check Free priority queue
237 // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing.
241 // free Tx(QueIdx) resources
242 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
246 // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870
247 NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE));
248 Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE), pData, Length);
249 if (Status != NDIS_STATUS_SUCCESS)
251 DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
255 //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
256 //pAd->CommonCfg.MlmeRate = RATE_2;
259 Status = MlmeDataHardTransmit(pAd, QueIdx, pPacket);
260 if (Status != NDIS_STATUS_SUCCESS)
261 RTMPFreeNdisPacket(pAd, pPacket);
262 retry = MAX_DATAMM_RETRY;
268 printk("retry %d\n", retry);
269 pAd->RalinkCounters.MgmtRingFullCount++;
271 if (retry >= MAX_DATAMM_RETRY)
273 DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in DataRing, MgmtRingFullCount=%ld!\n",
274 QueIdx, pAd->RalinkCounters.MgmtRingFullCount));
278 } while (retry < MAX_DATAMM_RETRY);
290 ========================================================================
293 Copy frame from waiting queue into relative ring buffer and set
294 appropriate ASIC register to kick hardware transmit function
297 pAd Pointer to our adapter
298 pBuffer Pointer to memory of outgoing frame
299 Length Size of outgoing management frame
307 IRQL = DISPATCH_LEVEL
311 ========================================================================
313 NDIS_STATUS MlmeHardTransmit(
314 IN PRTMP_ADAPTER pAd,
316 IN PNDIS_PACKET pPacket)
318 if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
321 return NDIS_STATUS_FAILURE;
324 return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
328 NDIS_STATUS MlmeDataHardTransmit(
329 IN PRTMP_ADAPTER pAd,
331 IN PNDIS_PACKET pPacket)
333 if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
336 return NDIS_STATUS_FAILURE;
340 return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
348 NDIS_STATUS MlmeHardTransmitMgmtRing(
349 IN PRTMP_ADAPTER pAd,
351 IN PNDIS_PACKET pPacket)
353 PACKET_INFO PacketInfo;
356 PHEADER_802_11 pHeader_802_11;
357 BOOLEAN bAckRequired, bInsertTimestamp;
359 PTXWI_STRUC pFirstTxWI;
360 MAC_TABLE_ENTRY *pMacEntry = NULL;
362 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
364 RTMP_SEM_LOCK(&pAd->MgmtRingLock);
367 if (pSrcBufVA == NULL)
369 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
370 return NDIS_STATUS_FAILURE;
373 // outgoing frame always wakeup PHY to prevent frame lost
374 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
375 AsicForceWakeup(pAd, TRUE);
377 pFirstTxWI = (PTXWI_STRUC)(pSrcBufVA + TXINFO_SIZE);
378 pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); //TXWI_SIZE);
380 if (pHeader_802_11->Addr1[0] & 0x01)
382 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
386 MlmeRate = pAd->CommonCfg.MlmeRate;
389 // Verify Mlme rate for a / g bands.
390 if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
393 if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
394 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
396 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
400 // Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode.
401 if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED
402 || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED
405 if (pAd->LatchRfRegs.Channel > 14)
406 pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
408 pAd->CommonCfg.MlmeTransmit.field.MODE = 0;
413 // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
414 // Snice it's been set to 0 while on MgtMacHeaderInit
415 // By the way this will cause frame to be send on PWR_SAVE failed.
417 // pHeader_802_11->FC.PwrMgmt = 0; // (pAd->StaCfg.Psm == PWR_SAVE);
419 // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
421 // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
422 if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL))
424 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
425 (pHeader_802_11->FC.SubType == SUBTYPE_ACTION))
426 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
428 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
431 bInsertTimestamp = FALSE;
432 if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
434 //Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue.
435 if ((pAd->OpMode == OPMODE_STA) && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL))
437 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
439 bAckRequired = FALSE;
441 else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
443 if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
445 bAckRequired = FALSE;
446 pHeader_802_11->Duration = 0;
451 pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
452 if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
454 bInsertTimestamp = TRUE;
459 pHeader_802_11->Sequence = pAd->Sequence++;
460 if (pAd->Sequence >0xfff)
463 // Before radar detection done, mgmt frame can not be sent but probe req
464 // Because we need to use probe req to trigger driver to send probe req in passive scan
465 if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
466 && (pAd->CommonCfg.bIEEE80211H == 1)
467 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
469 DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
470 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
471 return (NDIS_STATUS_FAILURE);
475 // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
476 // should always has only one ohysical buffer, and the whole frame size equals
477 // to the first scatter buffer size
480 // Initialize TX Descriptor
481 // For inter-frame gap, the number is for this frame and next frame
482 // For MLME rate, we will fix as 2Mb to match other vendor's implement
484 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
485 if (pMacEntry == NULL)
487 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
488 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
492 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
493 bInsertTimestamp, FALSE, bAckRequired, FALSE,
494 0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE),
495 pMacEntry->MaxHTPhyMode.field.MCS, 0,
496 (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
497 IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
500 // Now do hardware-depened kick out.
501 HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen);
503 // Make sure to release MGMT ring resource
504 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
505 return NDIS_STATUS_SUCCESS;
509 /********************************************************************************
511 New DeQueue Procedures.
513 ********************************************************************************/
515 #define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \
517 if (bIntContext == FALSE) \
518 RTMP_IRQ_LOCK((lock), IrqFlags); \
521 #define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \
523 if (bIntContext == FALSE) \
524 RTMP_IRQ_UNLOCK((lock), IrqFlags); \
529 ========================================================================
530 Tx Path design algorithm:
531 Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal),
532 Specific Packet Type. Following show the classification rule and policy for each kinds of packets.
533 Classification Rule=>
534 Multicast: (*addr1 & 0x01) == 0x01
535 Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc.
536 11N Rate : If peer support HT
537 (1).AMPDU -- If TXBA is negotiated.
538 (2).AMSDU -- If AMSDU is capable for both peer and ourself.
539 *). AMSDU can embedded in a AMPDU, but now we didn't support it.
540 (3).Normal -- Other packets which send as 11n rate.
542 B/G Rate : If peer is b/g only.
543 (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6
544 (2).Normal -- Other packets which send as b/g rate.
546 The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
548 Classified Packet Handle Rule=>
550 No ACK, //pTxBlk->bAckRequired = FALSE;
551 No WMM, //pTxBlk->bWMM = FALSE;
552 No piggyback, //pTxBlk->bPiggyBack = FALSE;
553 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
554 Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use
555 the same policy to handle it.
556 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
559 No piggyback, //pTxBlk->bPiggyBack = FALSE;
571 ========================================================================
573 static UCHAR TxPktClassification(
574 IN RTMP_ADAPTER *pAd,
575 IN PNDIS_PACKET pPacket)
577 UCHAR TxFrameType = TX_UNKOWN_FRAME;
579 MAC_TABLE_ENTRY *pMacEntry = NULL;
580 BOOLEAN bHTRate = FALSE;
582 Wcid = RTMP_GET_PACKET_WCID(pPacket);
583 if (Wcid == MCAST_WCID)
584 { // Handle for RA is Broadcast/Multicast Address.
585 return TX_MCAST_FRAME;
588 // Handle for unicast packets
589 pMacEntry = &pAd->MacTab.Content[Wcid];
590 if (RTMP_GET_PACKET_LOWRATE(pPacket))
591 { // It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame
592 TxFrameType = TX_LEGACY_FRAME;
594 else if (IS_HT_RATE(pMacEntry))
595 { // it's a 11n capable packet
597 // Depends on HTPhyMode to check if the peer support the HTRate transmission.
598 // Currently didn't support A-MSDU embedded in A-MPDU
600 if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE))
601 TxFrameType = TX_LEGACY_FRAME;
602 #ifdef UAPSD_AP_SUPPORT
603 else if (RTMP_GET_PACKET_EOSP(pPacket))
604 TxFrameType = TX_LEGACY_FRAME;
605 #endif // UAPSD_AP_SUPPORT //
606 else if((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0)
607 return TX_AMPDU_FRAME;
608 else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED))
609 return TX_AMSDU_FRAME;
611 TxFrameType = TX_LEGACY_FRAME;
614 { // it's a legacy b/g packet.
615 if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) &&
616 (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) &&
617 (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
618 { // if peer support Ralink Aggregation, we use it.
619 TxFrameType = TX_RALINK_FRAME;
623 TxFrameType = TX_LEGACY_FRAME;
627 // Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU.
628 if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) && (TxFrameType == TX_LEGACY_FRAME))
629 TxFrameType = TX_FRAG_FRAME;
635 BOOLEAN RTMP_FillTxBlkInfo(
636 IN RTMP_ADAPTER *pAd,
639 PACKET_INFO PacketInfo;
640 PNDIS_PACKET pPacket;
641 PMAC_TABLE_ENTRY pMacEntry = NULL;
643 pPacket = pTxBlk->pPacket;
644 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
646 pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket);
647 pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket);
648 pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket);
649 pTxBlk->FrameGap = IFS_HTTXOP; // ASIC determine Frame Gap
651 if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket))
652 TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame);
654 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame);
656 // Default to clear this flag
657 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS);
660 if (pTxBlk->Wcid == MCAST_WCID)
662 pTxBlk->pMacEntry = NULL;
664 #ifdef MCAST_RATE_SPECIFIC
665 PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket);
666 if (((*pDA & 0x01) == 0x01) && (*pDA != 0xff))
667 pTxBlk->pTransmit = &pAd->CommonCfg.MCastPhyMode;
669 #endif // MCAST_RATE_SPECIFIC //
670 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
673 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); // AckRequired = FALSE, when broadcast packet in Adhoc mode.
674 //TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate);
675 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag);
676 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
677 if (RTMP_GET_PACKET_MOREDATA(pPacket))
679 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
685 pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
686 pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode;
688 pMacEntry = pTxBlk->pMacEntry;
691 // For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK.
692 if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK)
693 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
695 TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired);
698 // If support WMM, enable it.
699 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
700 CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))
701 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM);
704 if (pTxBlk->TxFrameType == TX_LEGACY_FRAME)
706 if ( (RTMP_GET_PACKET_LOWRATE(pPacket)) ||
707 ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1)))
708 { // Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate.
709 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
711 // Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it???
712 if (IS_HT_STA(pTxBlk->pMacEntry) &&
713 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) &&
714 ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)))
716 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
717 TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS);
721 if ( (IS_HT_RATE(pMacEntry) == FALSE) &&
722 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE)))
723 { // Currently piggy-back only support when peer is operate in b/g mode.
724 TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack);
727 if (RTMP_GET_PACKET_MOREDATA(pPacket))
729 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
731 #ifdef UAPSD_AP_SUPPORT
732 if (RTMP_GET_PACKET_EOSP(pPacket))
734 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP);
736 #endif // UAPSD_AP_SUPPORT //
738 else if (pTxBlk->TxFrameType == TX_FRAG_FRAME)
740 TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag);
743 pMacEntry->DebugTxCount++;
753 BOOLEAN CanDoAggregateTransmit(
754 IN RTMP_ADAPTER *pAd,
755 IN NDIS_PACKET *pPacket,
759 //printk("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType);
761 if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
764 if (RTMP_GET_PACKET_DHCP(pPacket) ||
765 RTMP_GET_PACKET_EAPOL(pPacket) ||
766 RTMP_GET_PACKET_WAI(pPacket))
769 if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) &&
770 ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100)))
771 { // For AMSDU, allow the packets with total length < max-amsdu size
775 if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) &&
776 (pTxBlk->TxPacketList.Number == 2))
777 { // For RALINK-Aggregation, allow two frames in one batch.
781 if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP
789 ========================================================================
792 To do the enqueue operation and extract the first item of waiting
793 list. If a number of available shared memory segments could meet
794 the request of extracted item, the extracted item will be fragmented
795 into shared memory segments.
798 pAd Pointer to our adapter
799 pQueue Pointer to Waiting Queue
804 IRQL = DISPATCH_LEVEL
808 ========================================================================
810 VOID RTMPDeQueuePacket(
811 IN PRTMP_ADAPTER pAd,
812 IN BOOLEAN bIntContext,
813 IN UCHAR QIdx, /* BulkOutPipeId */
814 IN UCHAR Max_Tx_Packets)
816 PQUEUE_ENTRY pEntry = NULL;
817 PNDIS_PACKET pPacket;
818 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
820 PQUEUE_HEADER pQueue;
821 ULONG FreeNumber[NUM_OF_TX_RING];
822 UCHAR QueIdx, sQIdx, eQIdx;
823 unsigned long IrqFlags = 0;
824 BOOLEAN hasTxDesc = FALSE;
830 RtmpDiagStruct *pDiagStruct = &pAd->DiagStruct;
834 if (QIdx == NUM_OF_TX_RING)
837 //PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA)
838 eQIdx = 3; // 4 ACs, start from 0.
842 sQIdx = eQIdx = QIdx;
845 for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++)
849 RT28XX_START_DEQUEUE(pAd, QueIdx, IrqFlags);
852 firstRound = ((QueIdx == 0) ? TRUE : FALSE);
853 #endif // DBG_DIAGNOSE //
857 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |
858 fRTMP_ADAPTER_RADIO_OFF |
859 fRTMP_ADAPTER_RESET_IN_PROGRESS |
860 fRTMP_ADAPTER_HALT_IN_PROGRESS |
861 fRTMP_ADAPTER_NIC_NOT_EXIST))))
863 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
867 if (Count >= Max_Tx_Packets)
870 DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
871 if (&pAd->TxSwQueue[QueIdx] == NULL)
874 if (firstRound == TRUE)
875 pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][0]++;
876 #endif // DBG_DIAGNOSE //
877 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
882 // probe the Queue Head
883 pQueue = &pAd->TxSwQueue[QueIdx];
884 if ((pEntry = pQueue->Head) == NULL)
886 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
891 NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK));
892 pTxBlk->QueIdx = QueIdx;
894 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
896 // Early check to make sure we have enoguh Tx Resource.
897 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
900 pAd->PrivateInfo.TxRingFullCnt++;
902 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
907 pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
908 pEntry = RemoveHeadQueue(pQueue);
909 pTxBlk->TotalFrameNum++;
910 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
911 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
912 pTxBlk->pPacket = pPacket;
913 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
915 if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME)
917 // Enhance SW Aggregation Mechanism
918 if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType))
920 InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
921 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
926 if((pEntry = pQueue->Head) == NULL)
929 // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation.
930 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
931 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
932 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
933 if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE))
936 //Remove the packet from the TxSwQueue and insert into pTxBlk
937 pEntry = RemoveHeadQueue(pQueue);
939 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
940 pTxBlk->TotalFrameNum++;
941 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
942 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
943 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
946 if (pTxBlk->TxPacketList.Number == 1)
947 pTxBlk->TxFrameType = TX_LEGACY_FRAME;
951 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
954 Count += pTxBlk->TxPacketList.Number;
956 // Do HardTransmit now.
957 Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
960 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
964 RTUSBKickBulkOut(pAd);
972 ========================================================================
975 Calculates the duration which is required to transmit out frames
976 with given size and specified rate.
979 pAd Pointer to our adapter
981 Size Frame size in units of byte
984 Duration number in units of usec
987 IRQL = DISPATCH_LEVEL
991 ========================================================================
993 USHORT RTMPCalcDuration(
994 IN PRTMP_ADAPTER pAd,
1000 if (Rate < RATE_FIRST_OFDM_RATE) // CCK
1002 if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED))
1003 Duration = 96; // 72+24 preamble+plcp
1005 Duration = 192; // 144+48 preamble+plcp
1007 Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]);
1008 if ((Size << 4) % RateIdTo500Kbps[Rate])
1011 else if (Rate <= RATE_LAST_OFDM_RATE)// OFDM rates
1013 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
1014 Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
1015 if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
1020 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
1023 return (USHORT)Duration;
1028 ========================================================================
1030 Routine Description:
1031 Calculates the duration which is required to transmit out frames
1032 with given size and specified rate.
1035 pTxWI Pointer to head of each MPDU to HW.
1036 Ack Setting for Ack requirement bit
1037 Fragment Setting for Fragment bit
1038 RetryMode Setting for retry mode
1039 Ifs Setting for IFS gap
1040 Rate Setting for transmit rate
1041 Service Setting for service
1043 TxPreamble Short or Long preamble when using CCK rates
1044 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1049 IRQL = PASSIVE_LEVEL
1050 IRQL = DISPATCH_LEVEL
1052 See also : BASmartHardTransmit() !!!
1054 ========================================================================
1057 IN PRTMP_ADAPTER pAd,
1058 IN PTXWI_STRUC pOutTxWI,
1061 IN BOOLEAN InsTimestamp,
1064 IN BOOLEAN NSeq, // HW new a sequence.
1073 IN HTTRANSMIT_SETTING *pTransmit)
1075 PMAC_TABLE_ENTRY pMac = NULL;
1079 if (WCID < MAX_LEN_OF_MAC_TABLE)
1080 pMac = &pAd->MacTab.Content[WCID];
1083 // Always use Long preamble before verifiation short preamble functionality works well.
1084 // Todo: remove the following line if short preamble functionality works
1086 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1087 NdisZeroMemory(&TxWI, TXWI_SIZE);
1092 pTxWI->CFACK = CFACK;
1093 pTxWI->TS= InsTimestamp;
1094 pTxWI->AMPDU = AMPDU;
1096 pTxWI->txop= Txopmode;
1099 // John tune the performace with Intel Client in 20 MHz performance
1100 BASize = pAd->CommonCfg.TxBASize;
1104 pTxWI->BAWinSize = BASize;
1105 pTxWI->ShortGI = pTransmit->field.ShortGI;
1106 pTxWI->STBC = pTransmit->field.STBC;
1108 pTxWI->WirelessCliID = WCID;
1109 pTxWI->MPDUtotalByteCount = Length;
1110 pTxWI->PacketId = PID;
1112 // If CCK or OFDM, BW must be 20
1113 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1115 pTxWI->MCS = pTransmit->field.MCS;
1116 pTxWI->PHYMODE = pTransmit->field.MODE;
1117 pTxWI->CFACK = CfAck;
1121 if (pAd->CommonCfg.bMIMOPSEnable)
1123 if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1125 // Dynamic MIMO Power Save Mode
1128 else if (pMac->MmpsMode == MMPS_STATIC)
1130 // Static MIMO Power Save Mode
1131 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1138 //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;
1139 if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled))
1141 pTxWI->MpduDensity = 7;
1145 pTxWI->MpduDensity = pMac->MpduDensity;
1149 pTxWI->PacketId = pTxWI->MCS;
1150 NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC));
1154 VOID RTMPWriteTxWI_Data(
1155 IN PRTMP_ADAPTER pAd,
1156 IN OUT PTXWI_STRUC pTxWI,
1159 HTTRANSMIT_SETTING *pTransmit;
1160 PMAC_TABLE_ENTRY pMacEntry;
1165 pTransmit = pTxBlk->pTransmit;
1166 pMacEntry = pTxBlk->pMacEntry;
1170 // Always use Long preamble before verifiation short preamble functionality works well.
1171 // Todo: remove the following line if short preamble functionality works
1173 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1174 NdisZeroMemory(pTxWI, TXWI_SIZE);
1176 pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1177 pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1178 pTxWI->txop = pTxBlk->FrameGap;
1180 pTxWI->WirelessCliID = pTxBlk->Wcid;
1182 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1183 pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
1185 // If CCK or OFDM, BW must be 20
1186 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1187 pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
1189 // John tune the performace with Intel Client in 20 MHz performance
1190 BASize = pAd->CommonCfg.TxBASize;
1191 if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry))
1193 UCHAR RABAOriIdx = 0; //The RA's BA Originator table index.
1195 RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
1196 BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1199 pTxWI->TxBF = pTransmit->field.TxBF;
1200 pTxWI->BAWinSize = BASize;
1201 pTxWI->ShortGI = pTransmit->field.ShortGI;
1202 pTxWI->STBC = pTransmit->field.STBC;
1204 pTxWI->MCS = pTransmit->field.MCS;
1205 pTxWI->PHYMODE = pTransmit->field.MODE;
1209 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1211 // Dynamic MIMO Power Save Mode
1214 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1216 // Static MIMO Power Save Mode
1217 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1224 if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled))
1226 pTxWI->MpduDensity = 7;
1230 pTxWI->MpduDensity = pMacEntry->MpduDensity;
1235 if (pTxBlk->QueIdx== 0)
1237 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1238 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1240 #endif // DBG_DIAGNOSE //
1242 // for rate adapation
1243 pTxWI->PacketId = pTxWI->MCS;
1247 VOID RTMPWriteTxWI_Cache(
1248 IN PRTMP_ADAPTER pAd,
1249 IN OUT PTXWI_STRUC pTxWI,
1252 PHTTRANSMIT_SETTING pTransmit;
1253 PMAC_TABLE_ENTRY pMacEntry;
1258 pMacEntry = pTxBlk->pMacEntry;
1259 pTransmit = pTxBlk->pTransmit;
1261 if (pMacEntry->bAutoTxRateSwitch)
1263 pTxWI->txop = IFS_HTTXOP;
1265 // If CCK or OFDM, BW must be 20
1266 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1267 pTxWI->ShortGI = pTransmit->field.ShortGI;
1268 pTxWI->STBC = pTransmit->field.STBC;
1270 pTxWI->MCS = pTransmit->field.MCS;
1271 pTxWI->PHYMODE = pTransmit->field.MODE;
1273 // set PID for TxRateSwitching
1274 pTxWI->PacketId = pTransmit->field.MCS;
1277 pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE);
1280 if (pAd->CommonCfg.bMIMOPSEnable)
1282 // MIMO Power Save Mode
1283 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1285 // Dynamic MIMO Power Save Mode
1288 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1290 // Static MIMO Power Save Mode
1291 if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7))
1300 if (pTxBlk->QueIdx== 0)
1302 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1303 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1305 #endif // DBG_DIAGNOSE //
1307 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1313 ========================================================================
1315 Routine Description:
1316 Calculates the duration which is required to transmit out frames
1317 with given size and specified rate.
1320 pTxD Pointer to transmit descriptor
1321 Ack Setting for Ack requirement bit
1322 Fragment Setting for Fragment bit
1323 RetryMode Setting for retry mode
1324 Ifs Setting for IFS gap
1325 Rate Setting for transmit rate
1326 Service Setting for service
1328 TxPreamble Short or Long preamble when using CCK rates
1329 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1334 IRQL = PASSIVE_LEVEL
1335 IRQL = DISPATCH_LEVEL
1337 ========================================================================
1339 VOID RTMPWriteTxDescriptor(
1340 IN PRTMP_ADAPTER pAd,
1346 // Always use Long preamble before verifiation short preamble functionality works well.
1347 // Todo: remove the following line if short preamble functionality works
1349 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1351 pTxD->WIV = (bWIV) ? 1: 0;
1352 pTxD->QSEL= (QueueSEL);
1353 if (pAd->bGenOneHCCA == TRUE)
1354 pTxD->QSEL= FIFO_HCCA;
1359 // should be called only when -
1360 // 1. MEADIA_CONNECTED
1361 // 2. AGGREGATION_IN_USED
1362 // 3. Fragmentation not in used
1363 // 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible
1364 BOOLEAN TxFrameIsAggregatible(
1365 IN PRTMP_ADAPTER pAd,
1366 IN PUCHAR pPrevAddr1,
1370 // can't aggregate EAPOL (802.1x) frame
1371 if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1374 // can't aggregate multicast/broadcast frame
1375 if (p8023hdr[0] & 0x01)
1378 if (INFRA_ON(pAd)) // must be unicast to AP
1380 else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA
1388 ========================================================================
1390 Routine Description:
1391 Check the MSDU Aggregation policy
1392 1.HT aggregation is A-MSDU
1393 2.legaacy rate aggregation is software aggregation by Ralink.
1401 ========================================================================
1403 BOOLEAN PeerIsAggreOn(
1404 IN PRTMP_ADAPTER pAd,
1406 IN PMAC_TABLE_ENTRY pMacEntry)
1408 ULONG AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
1410 if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags))
1412 if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX)
1417 #ifdef AGGREGATION_SUPPORT
1418 if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
1419 { // legacy Ralink Aggregation support
1422 #endif // AGGREGATION_SUPPORT //
1431 ========================================================================
1433 Routine Description:
1434 Check and fine the packet waiting in SW queue with highest priority
1437 pAd Pointer to our adapter
1440 pQueue Pointer to Waiting Queue
1442 IRQL = DISPATCH_LEVEL
1446 ========================================================================
1448 PQUEUE_HEADER RTMPCheckTxSwQueue(
1449 IN PRTMP_ADAPTER pAd,
1455 Number = pAd->TxSwQueue[QID_AC_BK].Number
1456 + pAd->TxSwQueue[QID_AC_BE].Number
1457 + pAd->TxSwQueue[QID_AC_VI].Number
1458 + pAd->TxSwQueue[QID_AC_VO].Number
1459 + pAd->TxSwQueue[QID_HCCA].Number;
1461 if (pAd->TxSwQueue[QID_AC_VO].Head != NULL)
1463 *pQueIdx = QID_AC_VO;
1464 return (&pAd->TxSwQueue[QID_AC_VO]);
1466 else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL)
1468 *pQueIdx = QID_AC_VI;
1469 return (&pAd->TxSwQueue[QID_AC_VI]);
1471 else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL)
1473 *pQueIdx = QID_AC_BE;
1474 return (&pAd->TxSwQueue[QID_AC_BE]);
1476 else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL)
1478 *pQueIdx = QID_AC_BK;
1479 return (&pAd->TxSwQueue[QID_AC_BK]);
1481 else if (pAd->TxSwQueue[QID_HCCA].Head != NULL)
1483 *pQueIdx = QID_HCCA;
1484 return (&pAd->TxSwQueue[QID_HCCA]);
1487 // No packet pending in Tx Sw queue
1488 *pQueIdx = QID_AC_BK;
1496 ========================================================================
1498 Routine Description:
1499 Suspend MSDU transmission
1502 pAd Pointer to our adapter
1509 ========================================================================
1511 VOID RTMPSuspendMsduTransmission(
1512 IN PRTMP_ADAPTER pAd)
1514 DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n"));
1518 // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
1519 // use Lowbound as R66 value on ScanNextChannel(...)
1521 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue);
1523 // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)
1524 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd)));
1525 RTMPSetAGCInitValue(pAd, BW_20);
1527 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1528 //RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000); // abort all TX rings
1533 ========================================================================
1535 Routine Description:
1536 Resume MSDU transmission
1539 pAd Pointer to our adapter
1544 IRQL = DISPATCH_LEVEL
1548 ========================================================================
1550 VOID RTMPResumeMsduTransmission(
1551 IN PRTMP_ADAPTER pAd)
1553 DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
1556 // After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value
1557 // R66 should not be 0
1558 if (pAd->BbpTuning.R66CurrentValue == 0)
1560 pAd->BbpTuning.R66CurrentValue = 0x38;
1561 DBGPRINT_ERR(("RTMPResumeMsduTransmission, R66CurrentValue=0...\n"));
1563 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue);
1565 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1566 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1570 UINT deaggregate_AMSDU_announce(
1571 IN PRTMP_ADAPTER pAd,
1572 PNDIS_PACKET pPacket,
1577 USHORT SubFrameSize;
1578 PHEADER_802_3 pAMSDUsubheader;
1580 UCHAR Header802_3[14];
1582 PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP;
1583 PNDIS_PACKET pClonePacket;
1589 while (DataSize > LENGTH_802_3)
1594 pAMSDUsubheader = (PHEADER_802_3)pData;
1595 PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8);
1596 SubFrameSize = PayloadSize + LENGTH_802_3;
1599 if ((DataSize < SubFrameSize) || (PayloadSize > 1518 ))
1604 pPayload = pData + LENGTH_802_3;
1606 pSA = pData + MAC_ADDR_LEN;
1608 // convert to 802.3 header
1609 CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP);
1611 if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) )
1613 // avoid local heap overflow, use dyanamic allocation
1614 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
1615 memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize);
1616 Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize;
1617 WpaEAPOLKeyAction(pAd, Elem);
1622 if (pRemovedLLCSNAP)
1624 pPayload -= LENGTH_802_3;
1625 PayloadSize += LENGTH_802_3;
1626 NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3);
1630 pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
1633 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket));
1637 // A-MSDU has padding to multiple of 4 including subframe header.
1638 // align SubFrameSize up to multiple of 4
1639 SubFrameSize = (SubFrameSize+3)&(~0x3);
1642 if (SubFrameSize > 1528 || SubFrameSize < 32)
1647 if (DataSize > SubFrameSize)
1649 pData += SubFrameSize;
1650 DataSize -= SubFrameSize;
1659 // finally release original rx packet
1660 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1666 UINT BA_Reorder_AMSDU_Annnounce(
1667 IN PRTMP_ADAPTER pAd,
1668 IN PNDIS_PACKET pPacket)
1674 pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
1675 DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
1677 nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
1684 ==========================================================================
1686 Look up the MAC address in the MAC table. Return NULL if not found.
1688 pEntry - pointer to the MAC entry; NULL is not found
1689 ==========================================================================
1691 MAC_TABLE_ENTRY *MacTableLookup(
1692 IN PRTMP_ADAPTER pAd,
1696 MAC_TABLE_ENTRY *pEntry = NULL;
1698 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1699 pEntry = pAd->MacTab.Hash[HashIdx];
1701 while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh))
1703 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1708 pEntry = pEntry->pNext;
1714 MAC_TABLE_ENTRY *MacTableInsertEntry(
1715 IN PRTMP_ADAPTER pAd,
1718 IN BOOLEAN CleanAll)
1722 MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
1725 if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
1730 if (pAd->StaCfg.BssType == BSS_INFRA)
1733 // allocate one MAC entry
1734 NdisAcquireSpinLock(&pAd->MacTabLock);
1735 for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++) // skip entry#0 so that "entry index == AID" for fast lookup
1737 // pick up the first available vacancy
1738 if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
1739 (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
1740 (pAd->MacTab.Content[i].ValidAsApCli== FALSE) &&
1741 (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
1744 pEntry = &pAd->MacTab.Content[i];
1745 if (CleanAll == TRUE)
1747 pEntry->MaxSupportedRate = RATE_11;
1748 pEntry->CurrTxRate = RATE_11;
1749 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1750 pEntry->PairwiseKey.KeyLen = 0;
1751 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1755 pEntry->ValidAsCLI = TRUE;
1756 pEntry->ValidAsWDS = FALSE;
1757 pEntry->ValidAsApCli = FALSE;
1758 pEntry->ValidAsMesh = FALSE;
1759 pEntry->ValidAsDls = FALSE;
1763 pEntry->bIAmBadAtheros = FALSE;
1765 pEntry->CMTimerRunning = FALSE;
1766 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
1767 pEntry->RSNIE_Len = 0;
1768 NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
1769 pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
1771 if (pEntry->ValidAsMesh)
1772 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH);
1773 else if (pEntry->ValidAsApCli)
1774 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI);
1775 else if (pEntry->ValidAsWDS)
1776 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS);
1778 pEntry->apidx = apidx;
1782 pEntry->AuthMode = pAd->StaCfg.AuthMode;
1783 pEntry->WepStatus = pAd->StaCfg.WepStatus;
1784 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
1788 pEntry->GTKState = REKEY_NEGOTIATING;
1789 pEntry->PairwiseKey.KeyLen = 0;
1790 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1791 pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
1792 pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
1793 COPY_MAC_ADDR(pEntry->Addr, pAddr);
1794 pEntry->Sst = SST_NOT_AUTH;
1795 pEntry->AuthState = AS_NOT_AUTH;
1796 pEntry->Aid = (USHORT)i; //0;
1797 pEntry->CapabilityInfo = 0;
1798 pEntry->PsMode = PWR_ACTIVE;
1799 pEntry->PsQIdleCount = 0;
1800 pEntry->NoDataIdleCount = 0;
1801 pEntry->ContinueTxFailCnt = 0;
1802 InitializeQueueHeader(&pEntry->PsQueue);
1805 pAd->MacTab.Size ++;
1807 // Add this entry into ASIC RX WCID search table
1808 RT28XX_STA_ENTRY_ADD(pAd, pEntry);
1812 DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size));
1817 // add this MAC entry into HASH table
1820 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1821 if (pAd->MacTab.Hash[HashIdx] == NULL)
1823 pAd->MacTab.Hash[HashIdx] = pEntry;
1827 pCurrEntry = pAd->MacTab.Hash[HashIdx];
1828 while (pCurrEntry->pNext != NULL)
1829 pCurrEntry = pCurrEntry->pNext;
1830 pCurrEntry->pNext = pEntry;
1834 NdisReleaseSpinLock(&pAd->MacTabLock);
1839 ==========================================================================
1841 Delete a specified client from MAC table
1842 ==========================================================================
1844 BOOLEAN MacTableDeleteEntry(
1845 IN PRTMP_ADAPTER pAd,
1850 MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
1853 if (wcid >= MAX_LEN_OF_MAC_TABLE)
1856 NdisAcquireSpinLock(&pAd->MacTabLock);
1858 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1859 pEntry = &pAd->MacTab.Content[wcid];
1861 if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh
1864 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1867 // Delete this entry from ASIC on-chip WCID Table
1868 RT28XX_STA_ENTRY_MAC_RESET(pAd, wcid);
1870 // free resources of BA
1871 BASessionTearDownALL(pAd, pEntry->Aid);
1874 pProbeEntry = pAd->MacTab.Hash[HashIdx];
1875 ASSERT(pProbeEntry);
1880 if (pProbeEntry == pEntry)
1882 if (pPrevEntry == NULL)
1884 pAd->MacTab.Hash[HashIdx] = pEntry->pNext;
1888 pPrevEntry->pNext = pEntry->pNext;
1893 pPrevEntry = pProbeEntry;
1894 pProbeEntry = pProbeEntry->pNext;
1895 } while (pProbeEntry);
1898 ASSERT(pProbeEntry != NULL);
1900 RT28XX_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
1903 if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
1905 RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
1906 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
1910 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1911 pAd->MacTab.Size --;
1912 DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size));
1916 printk("\n%s: Impossible Wcid = %d !!!!!\n", __func__, wcid);
1920 NdisReleaseSpinLock(&pAd->MacTabLock);
1922 //Reset operating mode when no Sta.
1923 if (pAd->MacTab.Size == 0)
1925 pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
1926 RT28XX_UPDATE_PROTECT(pAd); // edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet
1934 ==========================================================================
1936 This routine reset the entire MAC table. All packets pending in
1937 the power-saving queues are freed here.
1938 ==========================================================================
1941 IN PRTMP_ADAPTER pAd)
1945 DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
1946 //NdisAcquireSpinLock(&pAd->MacTabLock);
1948 for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
1950 if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
1952 // free resources of BA
1953 BASessionTearDownALL(pAd, i);
1955 pAd->MacTab.Content[i].ValidAsCLI = FALSE;
1960 NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6);
1961 RT28XX_STA_ENTRY_MAC_RESET(pAd, i);
1964 //AsicDelWcidTab(pAd, i);
1972 ==========================================================================
1975 IRQL = DISPATCH_LEVEL
1977 ==========================================================================
1980 IN PRTMP_ADAPTER pAd,
1981 IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
1983 IN USHORT CapabilityInfo,
1985 IN USHORT ListenIntv)
1987 COPY_MAC_ADDR(AssocReq->Addr, pAddr);
1988 // Add mask to support 802.11b mode only
1989 AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request
1990 AssocReq->Timeout = Timeout;
1991 AssocReq->ListenIntv = ListenIntv;
1996 ==========================================================================
1999 IRQL = DISPATCH_LEVEL
2001 ==========================================================================
2003 VOID DisassocParmFill(
2004 IN PRTMP_ADAPTER pAd,
2005 IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
2009 COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
2010 DisassocReq->Reason = Reason;
2015 ========================================================================
2017 Routine Description:
2018 Check the out going frame, if this is an DHCP or ARP datagram
2019 will be duplicate another frame at low data rate transmit.
2022 pAd Pointer to our adapter
2023 pPacket Pointer to outgoing Ndis frame
2026 TRUE To be duplicate at Low data rate transmit. (1mb)
2029 IRQL = DISPATCH_LEVEL
2033 MAC header + IP Header + UDP Header
2037 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
2039 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
2042 port 0x43 means Bootstrap Protocol, server.
2043 Port 0x44 means Bootstrap Protocol, client.
2045 ========================================================================
2048 BOOLEAN RTMPCheckDHCPFrame(
2049 IN PRTMP_ADAPTER pAd,
2050 IN PNDIS_PACKET pPacket)
2052 PACKET_INFO PacketInfo;
2053 ULONG NumberOfBytesRead = 0;
2054 ULONG CurrentOffset = 0;
2055 PVOID pVirtualAddress = NULL;
2056 UINT NdisBufferLength;
2059 UCHAR ByteOffset36 = 0;
2060 UCHAR ByteOffset38 = 0;
2061 BOOLEAN ReadFirstParm = TRUE;
2063 RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength);
2065 NumberOfBytesRead += NdisBufferLength;
2066 pSrc = (PUCHAR) pVirtualAddress;
2067 Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
2070 // Check DHCP & BOOTP protocol
2072 while (NumberOfBytesRead <= PacketInfo.TotalPacketLength)
2074 if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE))
2076 CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength);
2077 ByteOffset36 = *(pSrc + CurrentOffset);
2078 ReadFirstParm = FALSE;
2081 if (NumberOfBytesRead >= 37)
2083 CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength);
2084 ByteOffset38 = *(pSrc + CurrentOffset);
2091 // Check for DHCP & BOOTP protocol
2092 if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43))
2095 // 2054 (hex 0806) for ARP datagrams
2096 // if this packet is not ARP datagrams, then do nothing
2097 // ARP datagrams will also be duplicate at 1mb broadcast frames
2099 if (Protocol != 0x0806 )
2107 BOOLEAN RTMPCheckEtherType(
2108 IN PRTMP_ADAPTER pAd,
2109 IN PNDIS_PACKET pPacket)
2115 UINT16 srcPort, dstPort;
2116 BOOLEAN status = TRUE;
2119 pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
2120 pktLen = GET_OS_PKT_LEN(pPacket);
2124 RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
2126 // get Ethernet protocol field
2127 TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13];
2129 pSrcBuf += LENGTH_802_3; // Skip the Ethernet Header.
2131 if (TypeLen <= 1500)
2132 { // 802.3, 802.3 LLC
2134 DestMAC(6) + SrcMAC(6) + Lenght(2) +
2135 DSAP(1) + SSAP(1) + Control(1) +
2136 if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
2137 => + SNAP (5, OriginationID(3) + etherType(2))
2139 if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03)
2141 Sniff2BytesFromNdisBuffer(pSrcBuf, 6, &Byte0, &Byte1);
2142 RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
2143 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2144 pSrcBuf += 8; // Skip this LLC/SNAP header
2148 //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.
2152 // If it's a VLAN packet, get the real Type/Length field.
2153 if (TypeLen == 0x8100)
2155 /* 0x8100 means VLAN packets */
2157 /* Dest. MAC Address (6-bytes) +
2158 Source MAC Address (6-bytes) +
2159 Length/Type = 802.1Q Tag Type (2-byte) +
2160 Tag Control Information (2-bytes) +
2161 Length / Type (2-bytes) +
2162 data payload (0-n bytes) +
2164 Frame Check Sequence (4-bytes) */
2166 RTMP_SET_PACKET_VLAN(pPacket, 1);
2167 Sniff2BytesFromNdisBuffer(pSrcBuf, 2, &Byte0, &Byte1);
2168 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2170 pSrcBuf += 4; // Skip the VLAN Header.
2177 ASSERT((pktLen > 34));
2178 if (*(pSrcBuf + 9) == 0x11)
2180 ASSERT((pktLen > 34)); // 14 for ethernet header, 20 for IP header
2182 pSrcBuf += 20; // Skip the IP header
2183 srcPort = OS_NTOHS(*((UINT16 *)pSrcBuf));
2184 dstPort = OS_NTOHS(*((UINT16 *)(pSrcBuf +2)));
2186 if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44))
2187 { //It's a BOOTP/DHCP packet
2188 RTMP_SET_PACKET_DHCP(pPacket, 1);
2196 RTMP_SET_PACKET_DHCP(pPacket, 1);
2202 RTMP_SET_PACKET_EAPOL(pPacket, 1);
2216 VOID Update_Rssi_Sample(
2217 IN PRTMP_ADAPTER pAd,
2218 IN RSSI_SAMPLE *pRssi,
2219 IN PRXWI_STRUC pRxWI)
2221 CHAR rssi0 = pRxWI->RSSI0;
2222 CHAR rssi1 = pRxWI->RSSI1;
2223 CHAR rssi2 = pRxWI->RSSI2;
2227 pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0);
2228 pRssi->AvgRssi0X8 = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
2229 pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
2234 pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1);
2235 pRssi->AvgRssi1X8 = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
2236 pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
2241 pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2);
2242 pRssi->AvgRssi2X8 = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
2243 pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
2249 // Normal legacy Rx packet indication
2250 VOID Indicate_Legacy_Packet(
2251 IN PRTMP_ADAPTER pAd,
2253 IN UCHAR FromWhichBSSID)
2255 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2256 UCHAR Header802_3[LENGTH_802_3];
2258 // 1. get 802.3 Header
2260 // a. pointer pRxBlk->pData to payload
2261 // b. modify pRxBlk->DataSize
2262 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2264 if (pRxBlk->DataSize > MAX_RX_PKT_LEN)
2267 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2272 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
2275 if (pAd->CommonCfg.bDisableReordering == 0)
2277 PBA_REC_ENTRY pBAEntry;
2279 UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID;
2280 UCHAR TID = pRxBlk->pRxWI->TID;
2283 #define REORDERING_PACKET_TIMEOUT ((100 * HZ)/1000) // system ticks -- 100 ms
2285 if (Wcid < MAX_LEN_OF_MAC_TABLE)
2287 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
2290 pBAEntry = &pAd->BATable.BARecEntry[Idx];
2291 // update last rx time
2292 NdisGetSystemUpTime(&Now32);
2293 if ((pBAEntry->list.qlen > 0) &&
2294 RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
2297 printk("Indicate_Legacy_Packet():flush reordering_timeout_mpdus! RxWI->Flags=%d, pRxWI.TID=%d, RxD->AMPDU=%d!\n", pRxBlk->Flags, pRxBlk->pRxWI->TID, pRxBlk->RxD.AMPDU);
2298 hex_dump("Dump the legacy Packet:", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), 64);
2299 ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
2306 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2309 // pass this 802.3 packet to upper layer or forward this packet to WM directly
2311 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
2315 // Normal, AMPDU or AMSDU
2316 VOID CmmRxnonRalinkFrameIndicate(
2317 IN PRTMP_ADAPTER pAd,
2319 IN UCHAR FromWhichBSSID)
2321 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
2323 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2327 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
2330 Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2334 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
2340 VOID CmmRxRalinkFrameIndicate(
2341 IN PRTMP_ADAPTER pAd,
2342 IN MAC_TABLE_ENTRY *pEntry,
2344 IN UCHAR FromWhichBSSID)
2346 UCHAR Header802_3[LENGTH_802_3];
2348 UINT16 Payload1Size, Payload2Size;
2350 PNDIS_PACKET pPacket2 = NULL;
2354 Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8);
2356 if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize))
2358 /* skip two byte MSDU2 len */
2360 pRxBlk->DataSize -= 2;
2365 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2369 // get 802.3 Header and remove LLC
2370 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2372 ASSERT(pRxBlk->pRxPacket);
2374 // Ralink Aggregation frame
2375 pAd->RalinkCounters.OneSecRxAggregationCount ++;
2376 Payload1Size = pRxBlk->DataSize - Msdu2Size;
2377 Payload2Size = Msdu2Size - LENGTH_802_3;
2379 pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
2381 pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID);
2386 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2390 // update payload size of 1st packet
2391 pRxBlk->DataSize = Payload1Size;
2392 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2394 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID);
2398 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
2403 #define RESET_FRAGFRAME(_fragFrame) \
2405 _fragFrame.RxSize = 0; \
2406 _fragFrame.Sequence = 0; \
2407 _fragFrame.LastFrag = 0; \
2408 _fragFrame.Flags = 0; \
2412 PNDIS_PACKET RTMPDeFragmentDataFrame(
2413 IN PRTMP_ADAPTER pAd,
2416 PHEADER_802_11 pHeader = pRxBlk->pHeader;
2417 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2418 UCHAR *pData = pRxBlk->pData;
2419 USHORT DataSize = pRxBlk->DataSize;
2420 PNDIS_PACKET pRetPacket = NULL;
2421 UCHAR *pFragBuffer = NULL;
2422 BOOLEAN bReassDone = FALSE;
2423 UCHAR HeaderRoom = 0;
2428 HeaderRoom = pData - (UCHAR *)pHeader;
2430 // Re-assemble the fragmented packets
2431 if (pHeader->Frag == 0) // Frag. Number is 0 : First frag or only one pkt
2433 // the first pkt of fragment, record it.
2434 if (pHeader->FC.MoreFrag)
2436 ASSERT(pAd->FragFrame.pFragPacket);
2437 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2438 pAd->FragFrame.RxSize = DataSize + HeaderRoom;
2439 NdisMoveMemory(pFragBuffer, pHeader, pAd->FragFrame.RxSize);
2440 pAd->FragFrame.Sequence = pHeader->Sequence;
2441 pAd->FragFrame.LastFrag = pHeader->Frag; // Should be 0
2442 ASSERT(pAd->FragFrame.LastFrag == 0);
2443 goto done; // end of processing this frame
2446 else //Middle & End of fragment
2448 if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
2449 (pHeader->Frag != (pAd->FragFrame.LastFrag + 1)))
2451 // Fragment is not the same sequence or out of fragment number order
2452 // Reset Fragment control blk
2453 RESET_FRAGFRAME(pAd->FragFrame);
2454 DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n"));
2455 goto done; // give up this frame
2457 else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE)
2459 // Fragment frame is too large, it exeeds the maximum frame size.
2460 // Reset Fragment control blk
2461 RESET_FRAGFRAME(pAd->FragFrame);
2462 DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
2463 goto done; // give up this frame
2467 // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.
2468 // In this case, we will dropt it.
2470 if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H)))
2472 DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag));
2473 goto done; // give up this frame
2476 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2478 // concatenate this fragment into the re-assembly buffer
2479 NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize);
2480 pAd->FragFrame.RxSize += DataSize;
2481 pAd->FragFrame.LastFrag = pHeader->Frag; // Update fragment number
2484 if (pHeader->FC.MoreFrag == FALSE)
2491 // always release rx fragmented packet
2492 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2494 // return defragmented packet if packet is reassembled completely
2495 // otherwise return NULL
2498 PNDIS_PACKET pNewFragPacket;
2500 // allocate a new packet buffer for fragment
2501 pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
2505 pRetPacket = pAd->FragFrame.pFragPacket;
2506 pAd->FragFrame.pFragPacket = pNewFragPacket;
2507 pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
2508 pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom;
2509 pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
2510 pRxBlk->pRxPacket = pRetPacket;
2514 RESET_FRAGFRAME(pAd->FragFrame);
2522 VOID Indicate_AMSDU_Packet(
2523 IN PRTMP_ADAPTER pAd,
2525 IN UCHAR FromWhichBSSID)
2529 update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
2530 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
2531 nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize);
2534 VOID Indicate_EAPOL_Packet(
2535 IN PRTMP_ADAPTER pAd,
2537 IN UCHAR FromWhichBSSID)
2539 MAC_TABLE_ENTRY *pEntry = NULL;
2542 pEntry = &pAd->MacTab.Content[BSSID_WCID];
2543 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
2549 DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
2551 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2556 #define BCN_TBTT_OFFSET 64 //defer 64 us
2557 VOID ReSyncBeaconTime(
2558 IN PRTMP_ADAPTER pAd)
2564 Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
2566 pAd->TbttTickCount++;
2569 // The updated BeaconInterval Value will affect Beacon Interval after two TBTT
2570 // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
2572 if (Offset == (BCN_TBTT_OFFSET-2))
2574 BCN_TIME_CFG_STRUC csr;
2575 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2576 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; // ASIC register in units of 1/16 TU = 64us
2577 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2581 if (Offset == (BCN_TBTT_OFFSET-1))
2583 BCN_TIME_CFG_STRUC csr;
2585 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2586 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU
2587 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);