2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 *************************************************************************
28 #include "../rt_config.h"
30 #define MAX_TX_IN_TBTT (16)
33 UCHAR SNAP_802_1H[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
34 UCHAR SNAP_BRIDGE_TUNNEL[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8};
35 // Add Cisco Aironet SNAP heade for CCX2 support
36 UCHAR SNAP_AIRONET[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00};
37 UCHAR CKIP_LLC_SNAP[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02};
38 UCHAR EAPOL_LLC_SNAP[]= {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e};
39 UCHAR EAPOL[] = {0x88, 0x8e};
40 UCHAR TPID[] = {0x81, 0x00}; /* VLAN related */
42 UCHAR IPX[] = {0x81, 0x37};
43 UCHAR APPLE_TALK[] = {0x80, 0xf3};
44 UCHAR RateIdToPlcpSignal[12] = {
45 0, /* RATE_1 */ 1, /* RATE_2 */ 2, /* RATE_5_5 */ 3, /* RATE_11 */ // see BBP spec
46 11, /* RATE_6 */ 15, /* RATE_9 */ 10, /* RATE_12 */ 14, /* RATE_18 */ // see IEEE802.11a-1999 p.14
47 9, /* RATE_24 */ 13, /* RATE_36 */ 8, /* RATE_48 */ 12 /* RATE_54 */ }; // see IEEE802.11a-1999 p.14
49 UCHAR OfdmSignalToRateId[16] = {
50 RATE_54, RATE_54, RATE_54, RATE_54, // OFDM PLCP Signal = 0, 1, 2, 3 respectively
51 RATE_54, RATE_54, RATE_54, RATE_54, // OFDM PLCP Signal = 4, 5, 6, 7 respectively
52 RATE_48, RATE_24, RATE_12, RATE_6, // OFDM PLCP Signal = 8, 9, 10, 11 respectively
53 RATE_54, RATE_36, RATE_18, RATE_9, // OFDM PLCP Signal = 12, 13, 14, 15 respectively
56 UCHAR OfdmRateToRxwiMCS[12] = {
58 0, 1, 2, 3, // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3
59 4, 5, 6, 7, // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7
61 UCHAR RxwiMCSToOfdmRate[12] = {
62 RATE_6, RATE_9, RATE_12, RATE_18,
63 RATE_24, RATE_36, RATE_48, RATE_54, // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3
64 4, 5, 6, 7, // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7
67 char* MCSToMbps[] = {"1Mbps","2Mbps","5.5Mbps","11Mbps","06Mbps","09Mbps","12Mbps","18Mbps","24Mbps","36Mbps","48Mbps","54Mbps","MM-0","MM-1","MM-2","MM-3","MM-4","MM-5","MM-6","MM-7","MM-8","MM-9","MM-10","MM-11","MM-12","MM-13","MM-14","MM-15","MM-32","ee1","ee2","ee3"};
69 UCHAR default_cwmin[]={CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1, CW_MIN_IN_BITS-2};
70 //UCHAR default_cwmax[]={CW_MAX_IN_BITS, CW_MAX_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1};
71 UCHAR default_sta_aifsn[]={3,7,2,2};
73 UCHAR MapUserPriorityToAccessCategory[8] = {QID_AC_BE, QID_AC_BK, QID_AC_BK, QID_AC_BE, QID_AC_VI, QID_AC_VI, QID_AC_VO, QID_AC_VO};
77 ========================================================================
80 API for MLME to transmit management frame to AP (BSS Mode)
81 or station (IBSS Mode)
84 pAd Pointer to our adapter
85 pData Pointer to the outgoing 802.11 frame
86 Length Size of outgoing management frame
98 ========================================================================
100 NDIS_STATUS MiniportMMRequest(
101 IN PRTMP_ADAPTER pAd,
106 PNDIS_PACKET pPacket;
107 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
110 UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN];
112 ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
118 IrqState = pAd->irq_disabled;
122 // Reset is in progress, stop immediately
123 if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
124 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)||
125 !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
127 Status = NDIS_STATUS_FAILURE;
131 // Check Free priority queue
132 // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing.
135 if (pAd->MACVersion == 0x28600100)
137 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
141 FreeNum = GET_MGMTRING_FREENO(pAd);
146 // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870
147 NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE));
148 Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE), pData, Length);
149 if (Status != NDIS_STATUS_SUCCESS)
151 DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
155 //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
156 //pAd->CommonCfg.MlmeRate = RATE_2;
159 Status = MlmeHardTransmit(pAd, QueIdx, pPacket);
160 if (Status != NDIS_STATUS_SUCCESS)
161 RTMPFreeNdisPacket(pAd, pPacket);
165 pAd->RalinkCounters.MgmtRingFullCount++;
166 DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n",
167 QueIdx, pAd->RalinkCounters.MgmtRingFullCount));
178 NDIS_STATUS MlmeDataHardTransmit(
179 IN PRTMP_ADAPTER pAd,
181 IN PNDIS_PACKET pPacket);
183 #define MAX_DATAMM_RETRY 3
185 ========================================================================
188 API for MLME to transmit management frame to AP (BSS Mode)
189 or station (IBSS Mode)
192 pAd Pointer to our adapter
193 pData Pointer to the outgoing 802.11 frame
194 Length Size of outgoing management frame
202 IRQL = DISPATCH_LEVEL
206 ========================================================================
208 NDIS_STATUS MiniportDataMMRequest(
209 IN PRTMP_ADAPTER pAd,
214 PNDIS_PACKET pPacket;
215 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
219 UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN];
221 ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
224 IrqState = pAd->irq_disabled;
228 // Reset is in progress, stop immediately
229 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
230 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)||
231 !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
233 Status = NDIS_STATUS_FAILURE;
237 // Check Free priority queue
238 // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing.
242 // free Tx(QueIdx) resources
243 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
247 // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870
248 NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE));
249 Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE), pData, Length);
250 if (Status != NDIS_STATUS_SUCCESS)
252 DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
256 //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
257 //pAd->CommonCfg.MlmeRate = RATE_2;
260 Status = MlmeDataHardTransmit(pAd, QueIdx, pPacket);
261 if (Status != NDIS_STATUS_SUCCESS)
262 RTMPFreeNdisPacket(pAd, pPacket);
263 retry = MAX_DATAMM_RETRY;
269 printk("retry %d\n", retry);
270 pAd->RalinkCounters.MgmtRingFullCount++;
272 if (retry >= MAX_DATAMM_RETRY)
274 DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in DataRing, MgmtRingFullCount=%ld!\n",
275 QueIdx, pAd->RalinkCounters.MgmtRingFullCount));
279 } while (retry < MAX_DATAMM_RETRY);
291 ========================================================================
294 Copy frame from waiting queue into relative ring buffer and set
295 appropriate ASIC register to kick hardware transmit function
298 pAd Pointer to our adapter
299 pBuffer Pointer to memory of outgoing frame
300 Length Size of outgoing management frame
308 IRQL = DISPATCH_LEVEL
312 ========================================================================
314 NDIS_STATUS MlmeHardTransmit(
315 IN PRTMP_ADAPTER pAd,
317 IN PNDIS_PACKET pPacket)
319 if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
322 return NDIS_STATUS_FAILURE;
325 return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
329 NDIS_STATUS MlmeDataHardTransmit(
330 IN PRTMP_ADAPTER pAd,
332 IN PNDIS_PACKET pPacket)
334 if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
337 return NDIS_STATUS_FAILURE;
341 return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
349 NDIS_STATUS MlmeHardTransmitMgmtRing(
350 IN PRTMP_ADAPTER pAd,
352 IN PNDIS_PACKET pPacket)
354 PACKET_INFO PacketInfo;
357 PHEADER_802_11 pHeader_802_11;
358 BOOLEAN bAckRequired, bInsertTimestamp;
360 PTXWI_STRUC pFirstTxWI;
361 MAC_TABLE_ENTRY *pMacEntry = NULL;
363 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
365 // Make sure MGMT ring resource won't be used by other threads
366 // sample, for IRQ LOCK -> SEM LOCK
367 // IrqState = pAd->irq_disabled;
369 RTMP_SEM_LOCK(&pAd->MgmtRingLock);
372 if (pSrcBufVA == NULL)
374 // The buffer shouldn't be NULL
376 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
377 return NDIS_STATUS_FAILURE;
380 // outgoing frame always wakeup PHY to prevent frame lost
381 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
382 AsicForceWakeup(pAd, TRUE);
384 pFirstTxWI = (PTXWI_STRUC)(pSrcBufVA + TXINFO_SIZE);
385 pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); //TXWI_SIZE);
387 if (pHeader_802_11->Addr1[0] & 0x01)
389 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
393 MlmeRate = pAd->CommonCfg.MlmeRate;
396 // Verify Mlme rate for a / g bands.
397 if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
400 if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
401 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
403 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
407 // Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode.
408 if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED
409 || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED
412 if (pAd->LatchRfRegs.Channel > 14)
413 pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
415 pAd->CommonCfg.MlmeTransmit.field.MODE = 0;
420 // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
421 // Snice it's been set to 0 while on MgtMacHeaderInit
422 // By the way this will cause frame to be send on PWR_SAVE failed.
424 // pHeader_802_11->FC.PwrMgmt = 0; // (pAd->StaCfg.Psm == PWR_SAVE);
426 // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
428 // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
429 if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL))
431 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
432 (pHeader_802_11->FC.SubType == SUBTYPE_ACTION))
433 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
435 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
438 bInsertTimestamp = FALSE;
439 if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
441 //Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue.
442 if ((pAd->OpMode == OPMODE_STA) && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL))
444 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
446 bAckRequired = FALSE;
448 else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
451 //pHeader_802_11->Sequence = pAd->Sequence;
453 if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
455 bAckRequired = FALSE;
456 pHeader_802_11->Duration = 0;
461 pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
462 if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
464 bInsertTimestamp = TRUE;
469 pHeader_802_11->Sequence = pAd->Sequence++;
470 if (pAd->Sequence >0xfff)
473 // Before radar detection done, mgmt frame can not be sent but probe req
474 // Because we need to use probe req to trigger driver to send probe req in passive scan
475 if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
476 && (pAd->CommonCfg.bIEEE80211H == 1)
477 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
479 DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
481 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
482 return (NDIS_STATUS_FAILURE);
486 // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
487 // should always has only one ohysical buffer, and the whole frame size equals
488 // to the first scatter buffer size
491 // Initialize TX Descriptor
492 // For inter-frame gap, the number is for this frame and next frame
493 // For MLME rate, we will fix as 2Mb to match other vendor's implement
494 // pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
496 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
497 if (pMacEntry == NULL)
499 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
500 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
504 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
505 bInsertTimestamp, FALSE, bAckRequired, FALSE,
506 0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE),
507 pMacEntry->MaxHTPhyMode.field.MCS, 0,
508 (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
509 IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
512 // Now do hardware-depened kick out.
513 HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen);
515 // Make sure to release MGMT ring resource
517 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
518 return NDIS_STATUS_SUCCESS;
522 /********************************************************************************
524 New DeQueue Procedures.
526 ********************************************************************************/
528 #define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \
530 if (bIntContext == FALSE) \
531 RTMP_IRQ_LOCK((lock), IrqFlags); \
534 #define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \
536 if (bIntContext == FALSE) \
537 RTMP_IRQ_UNLOCK((lock), IrqFlags); \
542 ========================================================================
543 Tx Path design algorithm:
544 Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal),
545 Specific Packet Type. Following show the classification rule and policy for each kinds of packets.
546 Classification Rule=>
547 Multicast: (*addr1 & 0x01) == 0x01
548 Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc.
549 11N Rate : If peer support HT
550 (1).AMPDU -- If TXBA is negotiated.
551 (2).AMSDU -- If AMSDU is capable for both peer and ourself.
552 *). AMSDU can embedded in a AMPDU, but now we didn't support it.
553 (3).Normal -- Other packets which send as 11n rate.
555 B/G Rate : If peer is b/g only.
556 (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6
557 (2).Normal -- Other packets which send as b/g rate.
559 The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
561 Classified Packet Handle Rule=>
563 No ACK, //pTxBlk->bAckRequired = FALSE;
564 No WMM, //pTxBlk->bWMM = FALSE;
565 No piggyback, //pTxBlk->bPiggyBack = FALSE;
566 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
567 Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use
568 the same policy to handle it.
569 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
572 No piggyback, //pTxBlk->bPiggyBack = FALSE;
584 ========================================================================
586 static UCHAR TxPktClassification(
587 IN RTMP_ADAPTER *pAd,
588 IN PNDIS_PACKET pPacket)
590 UCHAR TxFrameType = TX_UNKOWN_FRAME;
592 MAC_TABLE_ENTRY *pMacEntry = NULL;
593 BOOLEAN bHTRate = FALSE;
595 Wcid = RTMP_GET_PACKET_WCID(pPacket);
596 if (Wcid == MCAST_WCID)
597 { // Handle for RA is Broadcast/Multicast Address.
598 return TX_MCAST_FRAME;
601 // Handle for unicast packets
602 pMacEntry = &pAd->MacTab.Content[Wcid];
603 if (RTMP_GET_PACKET_LOWRATE(pPacket))
604 { // It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame
605 TxFrameType = TX_LEGACY_FRAME;
607 else if (IS_HT_RATE(pMacEntry))
608 { // it's a 11n capable packet
610 // Depends on HTPhyMode to check if the peer support the HTRate transmission.
611 // Currently didn't support A-MSDU embedded in A-MPDU
613 if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE))
614 TxFrameType = TX_LEGACY_FRAME;
615 #ifdef UAPSD_AP_SUPPORT
616 else if (RTMP_GET_PACKET_EOSP(pPacket))
617 TxFrameType = TX_LEGACY_FRAME;
618 #endif // UAPSD_AP_SUPPORT //
619 else if((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0)
620 return TX_AMPDU_FRAME;
621 else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED))
622 return TX_AMSDU_FRAME;
624 TxFrameType = TX_LEGACY_FRAME;
627 { // it's a legacy b/g packet.
628 if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) &&
629 (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) &&
630 (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
631 { // if peer support Ralink Aggregation, we use it.
632 TxFrameType = TX_RALINK_FRAME;
636 TxFrameType = TX_LEGACY_FRAME;
640 // Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU.
641 if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) && (TxFrameType == TX_LEGACY_FRAME))
642 TxFrameType = TX_FRAG_FRAME;
648 BOOLEAN RTMP_FillTxBlkInfo(
649 IN RTMP_ADAPTER *pAd,
652 PACKET_INFO PacketInfo;
653 PNDIS_PACKET pPacket;
654 PMAC_TABLE_ENTRY pMacEntry = NULL;
656 pPacket = pTxBlk->pPacket;
657 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
659 pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket);
660 pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket);
661 pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket);
662 pTxBlk->FrameGap = IFS_HTTXOP; // ASIC determine Frame Gap
664 if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket))
665 TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame);
667 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame);
669 // Default to clear this flag
670 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS);
673 if (pTxBlk->Wcid == MCAST_WCID)
675 pTxBlk->pMacEntry = NULL;
677 #ifdef MCAST_RATE_SPECIFIC
678 PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket);
679 if (((*pDA & 0x01) == 0x01) && (*pDA != 0xff))
680 pTxBlk->pTransmit = &pAd->CommonCfg.MCastPhyMode;
682 #endif // MCAST_RATE_SPECIFIC //
683 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
686 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); // AckRequired = FALSE, when broadcast packet in Adhoc mode.
687 //TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate);
688 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag);
689 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
690 if (RTMP_GET_PACKET_MOREDATA(pPacket))
692 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
698 pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
699 pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode;
701 pMacEntry = pTxBlk->pMacEntry;
704 // For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK.
705 if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK)
706 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
708 TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired);
711 // If support WMM, enable it.
712 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
713 CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))
714 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM);
716 // if (pAd->StaCfg.bAutoTxRateSwitch)
717 // TX_BLK_SET_FLAG(pTxBlk, fTX_AutoRateSwitch);
720 if (pTxBlk->TxFrameType == TX_LEGACY_FRAME)
722 if ( (RTMP_GET_PACKET_LOWRATE(pPacket)) ||
723 ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1)))
724 { // Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate.
725 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
727 // Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it???
728 if (IS_HT_STA(pTxBlk->pMacEntry) &&
729 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) &&
730 ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)))
732 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
733 TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS);
737 if ( (IS_HT_RATE(pMacEntry) == FALSE) &&
738 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE)))
739 { // Currently piggy-back only support when peer is operate in b/g mode.
740 TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack);
743 if (RTMP_GET_PACKET_MOREDATA(pPacket))
745 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
747 #ifdef UAPSD_AP_SUPPORT
748 if (RTMP_GET_PACKET_EOSP(pPacket))
750 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP);
752 #endif // UAPSD_AP_SUPPORT //
754 else if (pTxBlk->TxFrameType == TX_FRAG_FRAME)
756 TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag);
759 pMacEntry->DebugTxCount++;
769 BOOLEAN CanDoAggregateTransmit(
770 IN RTMP_ADAPTER *pAd,
771 IN NDIS_PACKET *pPacket,
775 //printk("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType);
777 if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
780 if (RTMP_GET_PACKET_DHCP(pPacket) ||
781 RTMP_GET_PACKET_EAPOL(pPacket) ||
782 RTMP_GET_PACKET_WAI(pPacket))
785 if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) &&
786 ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100)))
787 { // For AMSDU, allow the packets with total length < max-amsdu size
791 if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) &&
792 (pTxBlk->TxPacketList.Number == 2))
793 { // For RALINK-Aggregation, allow two frames in one batch.
797 if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP
805 ========================================================================
808 To do the enqueue operation and extract the first item of waiting
809 list. If a number of available shared memory segments could meet
810 the request of extracted item, the extracted item will be fragmented
811 into shared memory segments.
814 pAd Pointer to our adapter
815 pQueue Pointer to Waiting Queue
820 IRQL = DISPATCH_LEVEL
824 ========================================================================
826 VOID RTMPDeQueuePacket(
827 IN PRTMP_ADAPTER pAd,
828 IN BOOLEAN bIntContext,
829 IN UCHAR QIdx, /* BulkOutPipeId */
830 IN UCHAR Max_Tx_Packets)
832 PQUEUE_ENTRY pEntry = NULL;
833 PNDIS_PACKET pPacket;
834 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
836 PQUEUE_HEADER pQueue;
837 ULONG FreeNumber[NUM_OF_TX_RING];
838 UCHAR QueIdx, sQIdx, eQIdx;
839 unsigned long IrqFlags = 0;
840 BOOLEAN hasTxDesc = FALSE;
846 RtmpDiagStruct *pDiagStruct = &pAd->DiagStruct;
850 if (QIdx == NUM_OF_TX_RING)
853 //PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA)
854 eQIdx = 3; // 4 ACs, start from 0.
858 sQIdx = eQIdx = QIdx;
861 for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++)
865 RT28XX_START_DEQUEUE(pAd, QueIdx, IrqFlags);
868 firstRound = ((QueIdx == 0) ? TRUE : FALSE);
869 #endif // DBG_DIAGNOSE //
873 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |
874 fRTMP_ADAPTER_RADIO_OFF |
875 fRTMP_ADAPTER_RESET_IN_PROGRESS |
876 fRTMP_ADAPTER_HALT_IN_PROGRESS |
877 fRTMP_ADAPTER_NIC_NOT_EXIST))))
879 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
883 if (Count >= Max_Tx_Packets)
886 DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
887 if (&pAd->TxSwQueue[QueIdx] == NULL)
890 if (firstRound == TRUE)
891 pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][0]++;
892 #endif // DBG_DIAGNOSE //
893 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
898 // probe the Queue Head
899 pQueue = &pAd->TxSwQueue[QueIdx];
900 if ((pEntry = pQueue->Head) == NULL)
902 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
907 NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK));
908 //InitializeQueueHeader(&pTxBlk->TxPacketList); // Didn't need it because we already memzero it.
909 pTxBlk->QueIdx = QueIdx;
911 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
913 // Early check to make sure we have enoguh Tx Resource.
914 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
917 pAd->PrivateInfo.TxRingFullCnt++;
919 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
924 pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
925 pEntry = RemoveHeadQueue(pQueue);
926 pTxBlk->TotalFrameNum++;
927 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
928 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
929 pTxBlk->pPacket = pPacket;
930 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
932 if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME)
934 // Enhance SW Aggregation Mechanism
935 if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType))
937 InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
938 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
943 if((pEntry = pQueue->Head) == NULL)
946 // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation.
947 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
948 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
949 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
950 if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE))
953 //Remove the packet from the TxSwQueue and insert into pTxBlk
954 pEntry = RemoveHeadQueue(pQueue);
956 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
957 pTxBlk->TotalFrameNum++;
958 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
959 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
960 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
963 if (pTxBlk->TxPacketList.Number == 1)
964 pTxBlk->TxFrameType = TX_LEGACY_FRAME;
968 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
971 Count += pTxBlk->TxPacketList.Number;
973 // Do HardTransmit now.
974 Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
977 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
981 RTUSBKickBulkOut(pAd);
989 ========================================================================
992 Calculates the duration which is required to transmit out frames
993 with given size and specified rate.
996 pAd Pointer to our adapter
998 Size Frame size in units of byte
1001 Duration number in units of usec
1003 IRQL = PASSIVE_LEVEL
1004 IRQL = DISPATCH_LEVEL
1008 ========================================================================
1010 USHORT RTMPCalcDuration(
1011 IN PRTMP_ADAPTER pAd,
1017 if (Rate < RATE_FIRST_OFDM_RATE) // CCK
1019 if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED))
1020 Duration = 96; // 72+24 preamble+plcp
1022 Duration = 192; // 144+48 preamble+plcp
1024 Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]);
1025 if ((Size << 4) % RateIdTo500Kbps[Rate])
1028 else if (Rate <= RATE_LAST_OFDM_RATE)// OFDM rates
1030 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
1031 Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
1032 if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
1037 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
1040 return (USHORT)Duration;
1045 ========================================================================
1047 Routine Description:
1048 Calculates the duration which is required to transmit out frames
1049 with given size and specified rate.
1052 pTxWI Pointer to head of each MPDU to HW.
1053 Ack Setting for Ack requirement bit
1054 Fragment Setting for Fragment bit
1055 RetryMode Setting for retry mode
1056 Ifs Setting for IFS gap
1057 Rate Setting for transmit rate
1058 Service Setting for service
1060 TxPreamble Short or Long preamble when using CCK rates
1061 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1066 IRQL = PASSIVE_LEVEL
1067 IRQL = DISPATCH_LEVEL
1069 See also : BASmartHardTransmit() !!!
1071 ========================================================================
1074 IN PRTMP_ADAPTER pAd,
1075 IN PTXWI_STRUC pOutTxWI,
1078 IN BOOLEAN InsTimestamp,
1081 IN BOOLEAN NSeq, // HW new a sequence.
1090 IN HTTRANSMIT_SETTING *pTransmit)
1092 PMAC_TABLE_ENTRY pMac = NULL;
1096 if (WCID < MAX_LEN_OF_MAC_TABLE)
1097 pMac = &pAd->MacTab.Content[WCID];
1100 // Always use Long preamble before verifiation short preamble functionality works well.
1101 // Todo: remove the following line if short preamble functionality works
1103 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1104 NdisZeroMemory(&TxWI, TXWI_SIZE);
1109 pTxWI->CFACK = CFACK;
1110 pTxWI->TS= InsTimestamp;
1111 pTxWI->AMPDU = AMPDU;
1113 pTxWI->txop= Txopmode;
1116 // John tune the performace with Intel Client in 20 MHz performance
1117 BASize = pAd->CommonCfg.TxBASize;
1121 pTxWI->BAWinSize = BASize;
1122 pTxWI->ShortGI = pTransmit->field.ShortGI;
1123 pTxWI->STBC = pTransmit->field.STBC;
1125 pTxWI->WirelessCliID = WCID;
1126 pTxWI->MPDUtotalByteCount = Length;
1127 pTxWI->PacketId = PID;
1129 // If CCK or OFDM, BW must be 20
1130 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1132 pTxWI->MCS = pTransmit->field.MCS;
1133 pTxWI->PHYMODE = pTransmit->field.MODE;
1134 pTxWI->CFACK = CfAck;
1138 if (pAd->CommonCfg.bMIMOPSEnable)
1140 if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1142 // Dynamic MIMO Power Save Mode
1145 else if (pMac->MmpsMode == MMPS_STATIC)
1147 // Static MIMO Power Save Mode
1148 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1155 //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;
1156 if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled))
1158 pTxWI->MpduDensity = 7;
1162 pTxWI->MpduDensity = pMac->MpduDensity;
1166 pTxWI->PacketId = pTxWI->MCS;
1167 NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC));
1171 VOID RTMPWriteTxWI_Data(
1172 IN PRTMP_ADAPTER pAd,
1173 IN OUT PTXWI_STRUC pTxWI,
1176 HTTRANSMIT_SETTING *pTransmit;
1177 PMAC_TABLE_ENTRY pMacEntry;
1182 pTransmit = pTxBlk->pTransmit;
1183 pMacEntry = pTxBlk->pMacEntry;
1187 // Always use Long preamble before verifiation short preamble functionality works well.
1188 // Todo: remove the following line if short preamble functionality works
1190 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1191 NdisZeroMemory(pTxWI, TXWI_SIZE);
1193 pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1194 pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1195 pTxWI->txop = pTxBlk->FrameGap;
1197 pTxWI->WirelessCliID = pTxBlk->Wcid;
1199 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1200 pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
1202 // If CCK or OFDM, BW must be 20
1203 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1204 pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
1206 // John tune the performace with Intel Client in 20 MHz performance
1207 BASize = pAd->CommonCfg.TxBASize;
1208 if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry))
1210 UCHAR RABAOriIdx = 0; //The RA's BA Originator table index.
1212 RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
1213 BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1216 pTxWI->TxBF = pTransmit->field.TxBF;
1217 pTxWI->BAWinSize = BASize;
1218 pTxWI->ShortGI = pTransmit->field.ShortGI;
1219 pTxWI->STBC = pTransmit->field.STBC;
1221 pTxWI->MCS = pTransmit->field.MCS;
1222 pTxWI->PHYMODE = pTransmit->field.MODE;
1226 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1228 // Dynamic MIMO Power Save Mode
1231 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1233 // Static MIMO Power Save Mode
1234 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1241 if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled))
1243 pTxWI->MpduDensity = 7;
1247 pTxWI->MpduDensity = pMacEntry->MpduDensity;
1252 if (pTxBlk->QueIdx== 0)
1254 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1255 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1257 #endif // DBG_DIAGNOSE //
1259 // for rate adapation
1260 pTxWI->PacketId = pTxWI->MCS;
1264 VOID RTMPWriteTxWI_Cache(
1265 IN PRTMP_ADAPTER pAd,
1266 IN OUT PTXWI_STRUC pTxWI,
1269 PHTTRANSMIT_SETTING /*pTxHTPhyMode,*/ pTransmit;
1270 PMAC_TABLE_ENTRY pMacEntry;
1275 pMacEntry = pTxBlk->pMacEntry;
1276 pTransmit = pTxBlk->pTransmit;
1278 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
1279 //if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pMacEntry))
1280 //if (TX_BLK_TEST_FLAG(pTxBlk, fTX_AutoRateSwitch))
1281 if (pMacEntry->bAutoTxRateSwitch)
1283 pTxWI->txop = IFS_HTTXOP;
1285 // If CCK or OFDM, BW must be 20
1286 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1287 pTxWI->ShortGI = pTransmit->field.ShortGI;
1288 pTxWI->STBC = pTransmit->field.STBC;
1290 pTxWI->MCS = pTransmit->field.MCS;
1291 pTxWI->PHYMODE = pTransmit->field.MODE;
1293 // set PID for TxRateSwitching
1294 pTxWI->PacketId = pTransmit->field.MCS;
1297 pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE);
1300 if (pAd->CommonCfg.bMIMOPSEnable)
1302 // MIMO Power Save Mode
1303 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1305 // Dynamic MIMO Power Save Mode
1308 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1310 // Static MIMO Power Save Mode
1311 if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7))
1320 if (pTxBlk->QueIdx== 0)
1322 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1323 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1325 #endif // DBG_DIAGNOSE //
1327 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1333 ========================================================================
1335 Routine Description:
1336 Calculates the duration which is required to transmit out frames
1337 with given size and specified rate.
1340 pTxD Pointer to transmit descriptor
1341 Ack Setting for Ack requirement bit
1342 Fragment Setting for Fragment bit
1343 RetryMode Setting for retry mode
1344 Ifs Setting for IFS gap
1345 Rate Setting for transmit rate
1346 Service Setting for service
1348 TxPreamble Short or Long preamble when using CCK rates
1349 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1354 IRQL = PASSIVE_LEVEL
1355 IRQL = DISPATCH_LEVEL
1357 ========================================================================
1359 VOID RTMPWriteTxDescriptor(
1360 IN PRTMP_ADAPTER pAd,
1366 // Always use Long preamble before verifiation short preamble functionality works well.
1367 // Todo: remove the following line if short preamble functionality works
1369 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1371 pTxD->WIV = (bWIV) ? 1: 0;
1372 pTxD->QSEL= (QueueSEL);
1373 if (pAd->bGenOneHCCA == TRUE)
1374 pTxD->QSEL= FIFO_HCCA;
1379 // should be called only when -
1380 // 1. MEADIA_CONNECTED
1381 // 2. AGGREGATION_IN_USED
1382 // 3. Fragmentation not in used
1383 // 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible
1384 BOOLEAN TxFrameIsAggregatible(
1385 IN PRTMP_ADAPTER pAd,
1386 IN PUCHAR pPrevAddr1,
1390 // can't aggregate EAPOL (802.1x) frame
1391 if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1394 // can't aggregate multicast/broadcast frame
1395 if (p8023hdr[0] & 0x01)
1398 if (INFRA_ON(pAd)) // must be unicast to AP
1400 else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA
1408 ========================================================================
1410 Routine Description:
1411 Check the MSDU Aggregation policy
1412 1.HT aggregation is A-MSDU
1413 2.legaacy rate aggregation is software aggregation by Ralink.
1421 ========================================================================
1423 BOOLEAN PeerIsAggreOn(
1424 IN PRTMP_ADAPTER pAd,
1426 IN PMAC_TABLE_ENTRY pMacEntry)
1428 ULONG AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
1430 if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags))
1432 if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX)
1437 #ifdef AGGREGATION_SUPPORT
1438 if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
1439 { // legacy Ralink Aggregation support
1442 #endif // AGGREGATION_SUPPORT //
1451 ========================================================================
1453 Routine Description:
1454 Check and fine the packet waiting in SW queue with highest priority
1457 pAd Pointer to our adapter
1460 pQueue Pointer to Waiting Queue
1462 IRQL = DISPATCH_LEVEL
1466 ========================================================================
1468 PQUEUE_HEADER RTMPCheckTxSwQueue(
1469 IN PRTMP_ADAPTER pAd,
1474 // 2004-11-15 to be removed. test aggregation only
1475 // if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2))
1478 Number = pAd->TxSwQueue[QID_AC_BK].Number
1479 + pAd->TxSwQueue[QID_AC_BE].Number
1480 + pAd->TxSwQueue[QID_AC_VI].Number
1481 + pAd->TxSwQueue[QID_AC_VO].Number
1482 + pAd->TxSwQueue[QID_HCCA].Number;
1484 if (pAd->TxSwQueue[QID_AC_VO].Head != NULL)
1486 *pQueIdx = QID_AC_VO;
1487 return (&pAd->TxSwQueue[QID_AC_VO]);
1489 else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL)
1491 *pQueIdx = QID_AC_VI;
1492 return (&pAd->TxSwQueue[QID_AC_VI]);
1494 else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL)
1496 *pQueIdx = QID_AC_BE;
1497 return (&pAd->TxSwQueue[QID_AC_BE]);
1499 else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL)
1501 *pQueIdx = QID_AC_BK;
1502 return (&pAd->TxSwQueue[QID_AC_BK]);
1504 else if (pAd->TxSwQueue[QID_HCCA].Head != NULL)
1506 *pQueIdx = QID_HCCA;
1507 return (&pAd->TxSwQueue[QID_HCCA]);
1510 // No packet pending in Tx Sw queue
1511 *pQueIdx = QID_AC_BK;
1519 ========================================================================
1521 Routine Description:
1522 Suspend MSDU transmission
1525 pAd Pointer to our adapter
1532 ========================================================================
1534 VOID RTMPSuspendMsduTransmission(
1535 IN PRTMP_ADAPTER pAd)
1537 DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n"));
1541 // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
1542 // use Lowbound as R66 value on ScanNextChannel(...)
1544 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue);
1546 // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)
1547 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd)));
1548 RTMPSetAGCInitValue(pAd, BW_20);
1550 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1551 //RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000); // abort all TX rings
1556 ========================================================================
1558 Routine Description:
1559 Resume MSDU transmission
1562 pAd Pointer to our adapter
1567 IRQL = DISPATCH_LEVEL
1571 ========================================================================
1573 VOID RTMPResumeMsduTransmission(
1574 IN PRTMP_ADAPTER pAd)
1578 DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
1581 // After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value
1582 // R66 should not be 0
1583 if (pAd->BbpTuning.R66CurrentValue == 0)
1585 pAd->BbpTuning.R66CurrentValue = 0x38;
1586 DBGPRINT_ERR(("RTMPResumeMsduTransmission, R66CurrentValue=0...\n"));
1588 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue);
1590 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1591 // sample, for IRQ LOCK to SEM LOCK
1592 // IrqState = pAd->irq_disabled;
1594 // RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1596 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1600 UINT deaggregate_AMSDU_announce(
1601 IN PRTMP_ADAPTER pAd,
1602 PNDIS_PACKET pPacket,
1607 USHORT SubFrameSize;
1608 PHEADER_802_3 pAMSDUsubheader;
1610 UCHAR Header802_3[14];
1612 PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP;
1613 PNDIS_PACKET pClonePacket;
1619 while (DataSize > LENGTH_802_3)
1624 //hex_dump("subheader", pData, 64);
1625 pAMSDUsubheader = (PHEADER_802_3)pData;
1626 //pData += LENGTH_802_3;
1627 PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8);
1628 SubFrameSize = PayloadSize + LENGTH_802_3;
1631 if ((DataSize < SubFrameSize) || (PayloadSize > 1518 ))
1636 //printk("%d subframe: Size = %d\n", nMSDU, PayloadSize);
1638 pPayload = pData + LENGTH_802_3;
1640 pSA = pData + MAC_ADDR_LEN;
1642 // convert to 802.3 header
1643 CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP);
1645 if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) )
1647 // avoid local heap overflow, use dyanamic allocation
1648 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
1649 memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize);
1650 Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize;
1651 WpaEAPOLKeyAction(pAd, Elem);
1656 if (pRemovedLLCSNAP)
1658 pPayload -= LENGTH_802_3;
1659 PayloadSize += LENGTH_802_3;
1660 NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3);
1664 pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
1667 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket));
1671 // A-MSDU has padding to multiple of 4 including subframe header.
1672 // align SubFrameSize up to multiple of 4
1673 SubFrameSize = (SubFrameSize+3)&(~0x3);
1676 if (SubFrameSize > 1528 || SubFrameSize < 32)
1681 if (DataSize > SubFrameSize)
1683 pData += SubFrameSize;
1684 DataSize -= SubFrameSize;
1693 // finally release original rx packet
1694 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1700 UINT BA_Reorder_AMSDU_Annnounce(
1701 IN PRTMP_ADAPTER pAd,
1702 IN PNDIS_PACKET pPacket)
1708 pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
1709 DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
1711 nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
1718 ==========================================================================
1720 Look up the MAC address in the MAC table. Return NULL if not found.
1722 pEntry - pointer to the MAC entry; NULL is not found
1723 ==========================================================================
1725 MAC_TABLE_ENTRY *MacTableLookup(
1726 IN PRTMP_ADAPTER pAd,
1730 MAC_TABLE_ENTRY *pEntry = NULL;
1732 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1733 pEntry = pAd->MacTab.Hash[HashIdx];
1735 while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh))
1737 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1742 pEntry = pEntry->pNext;
1748 MAC_TABLE_ENTRY *MacTableInsertEntry(
1749 IN PRTMP_ADAPTER pAd,
1752 IN BOOLEAN CleanAll)
1756 MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
1761 if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
1766 if (pAd->StaCfg.BssType == BSS_INFRA)
1769 // allocate one MAC entry
1770 NdisAcquireSpinLock(&pAd->MacTabLock);
1771 for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++) // skip entry#0 so that "entry index == AID" for fast lookup
1773 // pick up the first available vacancy
1774 if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
1775 (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
1776 (pAd->MacTab.Content[i].ValidAsApCli== FALSE) &&
1777 (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
1780 pEntry = &pAd->MacTab.Content[i];
1781 if (CleanAll == TRUE)
1783 pEntry->MaxSupportedRate = RATE_11;
1784 pEntry->CurrTxRate = RATE_11;
1785 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1786 pEntry->PairwiseKey.KeyLen = 0;
1787 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1791 pEntry->ValidAsCLI = TRUE;
1792 pEntry->ValidAsWDS = FALSE;
1793 pEntry->ValidAsApCli = FALSE;
1794 pEntry->ValidAsMesh = FALSE;
1795 pEntry->ValidAsDls = FALSE;
1799 pEntry->bIAmBadAtheros = FALSE;
1801 pEntry->CMTimerRunning = FALSE;
1802 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
1803 pEntry->RSNIE_Len = 0;
1804 NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
1805 pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
1807 if (pEntry->ValidAsMesh)
1808 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH);
1809 else if (pEntry->ValidAsApCli)
1810 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI);
1811 else if (pEntry->ValidAsWDS)
1812 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS);
1814 pEntry->apidx = apidx;
1818 pEntry->AuthMode = pAd->StaCfg.AuthMode;
1819 pEntry->WepStatus = pAd->StaCfg.WepStatus;
1820 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
1824 pEntry->GTKState = REKEY_NEGOTIATING;
1825 pEntry->PairwiseKey.KeyLen = 0;
1826 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1827 pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
1828 pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
1829 COPY_MAC_ADDR(pEntry->Addr, pAddr);
1830 pEntry->Sst = SST_NOT_AUTH;
1831 pEntry->AuthState = AS_NOT_AUTH;
1832 pEntry->Aid = (USHORT)i; //0;
1833 pEntry->CapabilityInfo = 0;
1834 pEntry->PsMode = PWR_ACTIVE;
1835 pEntry->PsQIdleCount = 0;
1836 pEntry->NoDataIdleCount = 0;
1837 pEntry->ContinueTxFailCnt = 0;
1838 InitializeQueueHeader(&pEntry->PsQueue);
1841 pAd->MacTab.Size ++;
1843 // Add this entry into ASIC RX WCID search table
1844 RT28XX_STA_ENTRY_ADD(pAd, pEntry);
1848 DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size));
1853 // add this MAC entry into HASH table
1856 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1857 if (pAd->MacTab.Hash[HashIdx] == NULL)
1859 pAd->MacTab.Hash[HashIdx] = pEntry;
1863 pCurrEntry = pAd->MacTab.Hash[HashIdx];
1864 while (pCurrEntry->pNext != NULL)
1865 pCurrEntry = pCurrEntry->pNext;
1866 pCurrEntry->pNext = pEntry;
1870 NdisReleaseSpinLock(&pAd->MacTabLock);
1875 ==========================================================================
1877 Delete a specified client from MAC table
1878 ==========================================================================
1880 BOOLEAN MacTableDeleteEntry(
1881 IN PRTMP_ADAPTER pAd,
1886 MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
1888 //USHORT offset; // unused variable
1889 //UCHAR j; // unused variable
1891 if (wcid >= MAX_LEN_OF_MAC_TABLE)
1894 NdisAcquireSpinLock(&pAd->MacTabLock);
1896 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1897 //pEntry = pAd->MacTab.Hash[HashIdx];
1898 pEntry = &pAd->MacTab.Content[wcid];
1900 if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh
1903 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1906 // Delete this entry from ASIC on-chip WCID Table
1907 RT28XX_STA_ENTRY_MAC_RESET(pAd, wcid);
1909 // free resources of BA
1910 BASessionTearDownALL(pAd, pEntry->Aid);
1913 pProbeEntry = pAd->MacTab.Hash[HashIdx];
1914 ASSERT(pProbeEntry);
1919 if (pProbeEntry == pEntry)
1921 if (pPrevEntry == NULL)
1923 pAd->MacTab.Hash[HashIdx] = pEntry->pNext;
1927 pPrevEntry->pNext = pEntry->pNext;
1932 pPrevEntry = pProbeEntry;
1933 pProbeEntry = pProbeEntry->pNext;
1934 } while (pProbeEntry);
1937 ASSERT(pProbeEntry != NULL);
1939 RT28XX_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
1942 if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
1944 RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
1945 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
1949 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1950 pAd->MacTab.Size --;
1951 DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size));
1955 printk("\n%s: Impossible Wcid = %d !!!!!\n", __func__, wcid);
1959 NdisReleaseSpinLock(&pAd->MacTabLock);
1961 //Reset operating mode when no Sta.
1962 if (pAd->MacTab.Size == 0)
1964 pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
1965 //AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/);
1966 RT28XX_UPDATE_PROTECT(pAd); // edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet
1974 ==========================================================================
1976 This routine reset the entire MAC table. All packets pending in
1977 the power-saving queues are freed here.
1978 ==========================================================================
1981 IN PRTMP_ADAPTER pAd)
1985 DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
1986 //NdisAcquireSpinLock(&pAd->MacTabLock);
1988 for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
1990 if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
1992 // free resources of BA
1993 BASessionTearDownALL(pAd, i);
1995 pAd->MacTab.Content[i].ValidAsCLI = FALSE;
2000 NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6);
2001 RT28XX_STA_ENTRY_MAC_RESET(pAd, i);
2004 //AsicDelWcidTab(pAd, i);
2012 ==========================================================================
2015 IRQL = DISPATCH_LEVEL
2017 ==========================================================================
2020 IN PRTMP_ADAPTER pAd,
2021 IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
2023 IN USHORT CapabilityInfo,
2025 IN USHORT ListenIntv)
2027 COPY_MAC_ADDR(AssocReq->Addr, pAddr);
2028 // Add mask to support 802.11b mode only
2029 AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request
2030 AssocReq->Timeout = Timeout;
2031 AssocReq->ListenIntv = ListenIntv;
2036 ==========================================================================
2039 IRQL = DISPATCH_LEVEL
2041 ==========================================================================
2043 VOID DisassocParmFill(
2044 IN PRTMP_ADAPTER pAd,
2045 IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
2049 COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
2050 DisassocReq->Reason = Reason;
2055 ========================================================================
2057 Routine Description:
2058 Check the out going frame, if this is an DHCP or ARP datagram
2059 will be duplicate another frame at low data rate transmit.
2062 pAd Pointer to our adapter
2063 pPacket Pointer to outgoing Ndis frame
2066 TRUE To be duplicate at Low data rate transmit. (1mb)
2069 IRQL = DISPATCH_LEVEL
2073 MAC header + IP Header + UDP Header
2077 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
2079 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
2082 port 0x43 means Bootstrap Protocol, server.
2083 Port 0x44 means Bootstrap Protocol, client.
2085 ========================================================================
2088 BOOLEAN RTMPCheckDHCPFrame(
2089 IN PRTMP_ADAPTER pAd,
2090 IN PNDIS_PACKET pPacket)
2092 PACKET_INFO PacketInfo;
2093 ULONG NumberOfBytesRead = 0;
2094 ULONG CurrentOffset = 0;
2095 PVOID pVirtualAddress = NULL;
2096 UINT NdisBufferLength;
2099 UCHAR ByteOffset36 = 0;
2100 UCHAR ByteOffset38 = 0;
2101 BOOLEAN ReadFirstParm = TRUE;
2103 RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength);
2105 NumberOfBytesRead += NdisBufferLength;
2106 pSrc = (PUCHAR) pVirtualAddress;
2107 Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
2110 // Check DHCP & BOOTP protocol
2112 while (NumberOfBytesRead <= PacketInfo.TotalPacketLength)
2114 if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE))
2116 CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength);
2117 ByteOffset36 = *(pSrc + CurrentOffset);
2118 ReadFirstParm = FALSE;
2121 if (NumberOfBytesRead >= 37)
2123 CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength);
2124 ByteOffset38 = *(pSrc + CurrentOffset);
2131 // Check for DHCP & BOOTP protocol
2132 if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43))
2135 // 2054 (hex 0806) for ARP datagrams
2136 // if this packet is not ARP datagrams, then do nothing
2137 // ARP datagrams will also be duplicate at 1mb broadcast frames
2139 if (Protocol != 0x0806 )
2147 BOOLEAN RTMPCheckEtherType(
2148 IN PRTMP_ADAPTER pAd,
2149 IN PNDIS_PACKET pPacket)
2155 UINT16 srcPort, dstPort;
2156 BOOLEAN status = TRUE;
2159 pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
2160 pktLen = GET_OS_PKT_LEN(pPacket);
2164 RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
2166 // get Ethernet protocol field
2167 TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13];
2169 pSrcBuf += LENGTH_802_3; // Skip the Ethernet Header.
2171 if (TypeLen <= 1500)
2172 { // 802.3, 802.3 LLC
2174 DestMAC(6) + SrcMAC(6) + Lenght(2) +
2175 DSAP(1) + SSAP(1) + Control(1) +
2176 if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
2177 => + SNAP (5, OriginationID(3) + etherType(2))
2179 if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03)
2181 Sniff2BytesFromNdisBuffer(pSrcBuf, 6, &Byte0, &Byte1);
2182 RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
2183 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2184 pSrcBuf += 8; // Skip this LLC/SNAP header
2188 //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.
2192 // If it's a VLAN packet, get the real Type/Length field.
2193 if (TypeLen == 0x8100)
2195 /* 0x8100 means VLAN packets */
2197 /* Dest. MAC Address (6-bytes) +
2198 Source MAC Address (6-bytes) +
2199 Length/Type = 802.1Q Tag Type (2-byte) +
2200 Tag Control Information (2-bytes) +
2201 Length / Type (2-bytes) +
2202 data payload (0-n bytes) +
2204 Frame Check Sequence (4-bytes) */
2206 RTMP_SET_PACKET_VLAN(pPacket, 1);
2207 Sniff2BytesFromNdisBuffer(pSrcBuf, 2, &Byte0, &Byte1);
2208 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2210 pSrcBuf += 4; // Skip the VLAN Header.
2217 ASSERT((pktLen > 34));
2218 if (*(pSrcBuf + 9) == 0x11)
2220 ASSERT((pktLen > 34)); // 14 for ethernet header, 20 for IP header
2222 pSrcBuf += 20; // Skip the IP header
2223 srcPort = OS_NTOHS(*((UINT16 *)pSrcBuf));
2224 dstPort = OS_NTOHS(*((UINT16 *)(pSrcBuf +2)));
2226 if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44))
2227 { //It's a BOOTP/DHCP packet
2228 RTMP_SET_PACKET_DHCP(pPacket, 1);
2236 RTMP_SET_PACKET_DHCP(pPacket, 1);
2242 RTMP_SET_PACKET_EAPOL(pPacket, 1);
2256 VOID Update_Rssi_Sample(
2257 IN PRTMP_ADAPTER pAd,
2258 IN RSSI_SAMPLE *pRssi,
2259 IN PRXWI_STRUC pRxWI)
2261 CHAR rssi0 = pRxWI->RSSI0;
2262 CHAR rssi1 = pRxWI->RSSI1;
2263 CHAR rssi2 = pRxWI->RSSI2;
2267 pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0);
2268 pRssi->AvgRssi0X8 = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
2269 pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
2274 pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1);
2275 pRssi->AvgRssi1X8 = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
2276 pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
2281 pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2);
2282 pRssi->AvgRssi2X8 = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
2283 pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
2289 // Normal legacy Rx packet indication
2290 VOID Indicate_Legacy_Packet(
2291 IN PRTMP_ADAPTER pAd,
2293 IN UCHAR FromWhichBSSID)
2295 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2296 UCHAR Header802_3[LENGTH_802_3];
2298 // 1. get 802.3 Header
2300 // a. pointer pRxBlk->pData to payload
2301 // b. modify pRxBlk->DataSize
2302 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2304 if (pRxBlk->DataSize > MAX_RX_PKT_LEN)
2307 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2312 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
2315 if (pAd->CommonCfg.bDisableReordering == 0)
2317 PBA_REC_ENTRY pBAEntry;
2319 UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID;
2320 UCHAR TID = pRxBlk->pRxWI->TID;
2323 #define REORDERING_PACKET_TIMEOUT ((100 * HZ)/1000) // system ticks -- 100 ms
2325 if (Wcid < MAX_LEN_OF_MAC_TABLE)
2327 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
2330 pBAEntry = &pAd->BATable.BARecEntry[Idx];
2331 // update last rx time
2332 NdisGetSystemUpTime(&Now32);
2333 if ((pBAEntry->list.qlen > 0) &&
2334 RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
2337 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);
2338 hex_dump("Dump the legacy Packet:", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), 64);
2339 ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
2346 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2349 // pass this 802.3 packet to upper layer or forward this packet to WM directly
2351 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
2355 // Normal, AMPDU or AMSDU
2356 VOID CmmRxnonRalinkFrameIndicate(
2357 IN PRTMP_ADAPTER pAd,
2359 IN UCHAR FromWhichBSSID)
2361 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
2363 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2367 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
2370 Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2374 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
2380 VOID CmmRxRalinkFrameIndicate(
2381 IN PRTMP_ADAPTER pAd,
2382 IN MAC_TABLE_ENTRY *pEntry,
2384 IN UCHAR FromWhichBSSID)
2386 UCHAR Header802_3[LENGTH_802_3];
2388 UINT16 Payload1Size, Payload2Size;
2390 PNDIS_PACKET pPacket2 = NULL;
2394 Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8);
2396 if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize))
2398 /* skip two byte MSDU2 len */
2400 pRxBlk->DataSize -= 2;
2405 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2409 // get 802.3 Header and remove LLC
2410 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2412 ASSERT(pRxBlk->pRxPacket);
2414 // Ralink Aggregation frame
2415 pAd->RalinkCounters.OneSecRxAggregationCount ++;
2416 Payload1Size = pRxBlk->DataSize - Msdu2Size;
2417 Payload2Size = Msdu2Size - LENGTH_802_3;
2419 pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
2421 pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID);
2426 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2430 // update payload size of 1st packet
2431 pRxBlk->DataSize = Payload1Size;
2432 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2434 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID);
2438 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
2443 #define RESET_FRAGFRAME(_fragFrame) \
2445 _fragFrame.RxSize = 0; \
2446 _fragFrame.Sequence = 0; \
2447 _fragFrame.LastFrag = 0; \
2448 _fragFrame.Flags = 0; \
2452 PNDIS_PACKET RTMPDeFragmentDataFrame(
2453 IN PRTMP_ADAPTER pAd,
2456 PHEADER_802_11 pHeader = pRxBlk->pHeader;
2457 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2458 UCHAR *pData = pRxBlk->pData;
2459 USHORT DataSize = pRxBlk->DataSize;
2460 PNDIS_PACKET pRetPacket = NULL;
2461 UCHAR *pFragBuffer = NULL;
2462 BOOLEAN bReassDone = FALSE;
2463 UCHAR HeaderRoom = 0;
2468 HeaderRoom = pData - (UCHAR *)pHeader;
2470 // Re-assemble the fragmented packets
2471 if (pHeader->Frag == 0) // Frag. Number is 0 : First frag or only one pkt
2473 // the first pkt of fragment, record it.
2474 if (pHeader->FC.MoreFrag)
2476 ASSERT(pAd->FragFrame.pFragPacket);
2477 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2478 pAd->FragFrame.RxSize = DataSize + HeaderRoom;
2479 NdisMoveMemory(pFragBuffer, pHeader, pAd->FragFrame.RxSize);
2480 pAd->FragFrame.Sequence = pHeader->Sequence;
2481 pAd->FragFrame.LastFrag = pHeader->Frag; // Should be 0
2482 ASSERT(pAd->FragFrame.LastFrag == 0);
2483 goto done; // end of processing this frame
2486 else //Middle & End of fragment
2488 if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
2489 (pHeader->Frag != (pAd->FragFrame.LastFrag + 1)))
2491 // Fragment is not the same sequence or out of fragment number order
2492 // Reset Fragment control blk
2493 RESET_FRAGFRAME(pAd->FragFrame);
2494 DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n"));
2495 goto done; // give up this frame
2497 else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE)
2499 // Fragment frame is too large, it exeeds the maximum frame size.
2500 // Reset Fragment control blk
2501 RESET_FRAGFRAME(pAd->FragFrame);
2502 DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
2503 goto done; // give up this frame
2507 // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.
2508 // In this case, we will dropt it.
2510 if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H)))
2512 DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag));
2513 goto done; // give up this frame
2516 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2518 // concatenate this fragment into the re-assembly buffer
2519 NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize);
2520 pAd->FragFrame.RxSize += DataSize;
2521 pAd->FragFrame.LastFrag = pHeader->Frag; // Update fragment number
2524 if (pHeader->FC.MoreFrag == FALSE)
2531 // always release rx fragmented packet
2532 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2534 // return defragmented packet if packet is reassembled completely
2535 // otherwise return NULL
2538 PNDIS_PACKET pNewFragPacket;
2540 // allocate a new packet buffer for fragment
2541 pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
2545 pRetPacket = pAd->FragFrame.pFragPacket;
2546 pAd->FragFrame.pFragPacket = pNewFragPacket;
2547 pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
2548 pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom;
2549 pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
2550 pRxBlk->pRxPacket = pRetPacket;
2554 RESET_FRAGFRAME(pAd->FragFrame);
2562 VOID Indicate_AMSDU_Packet(
2563 IN PRTMP_ADAPTER pAd,
2565 IN UCHAR FromWhichBSSID)
2569 update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
2570 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
2571 nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize);
2574 VOID Indicate_EAPOL_Packet(
2575 IN PRTMP_ADAPTER pAd,
2577 IN UCHAR FromWhichBSSID)
2579 MAC_TABLE_ENTRY *pEntry = NULL;
2582 pEntry = &pAd->MacTab.Content[BSSID_WCID];
2583 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
2589 DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
2591 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2596 #define BCN_TBTT_OFFSET 64 //defer 64 us
2597 VOID ReSyncBeaconTime(
2598 IN PRTMP_ADAPTER pAd)
2604 Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
2606 pAd->TbttTickCount++;
2609 // The updated BeaconInterval Value will affect Beacon Interval after two TBTT
2610 // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
2612 if (Offset == (BCN_TBTT_OFFSET-2))
2614 BCN_TIME_CFG_STRUC csr;
2615 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2616 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; // ASIC register in units of 1/16 TU = 64us
2617 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2621 if (Offset == (BCN_TBTT_OFFSET-1))
2623 BCN_TIME_CFG_STRUC csr;
2625 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2626 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU
2627 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);