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));
176 NDIS_STATUS MlmeDataHardTransmit(
177 IN PRTMP_ADAPTER pAd,
179 IN PNDIS_PACKET pPacket);
181 #define MAX_DATAMM_RETRY 3
183 ========================================================================
186 API for MLME to transmit management frame to AP (BSS Mode)
187 or station (IBSS Mode)
190 pAd Pointer to our adapter
191 pData Pointer to the outgoing 802.11 frame
192 Length Size of outgoing management frame
200 IRQL = DISPATCH_LEVEL
204 ========================================================================
206 NDIS_STATUS MiniportDataMMRequest(
207 IN PRTMP_ADAPTER pAd,
212 PNDIS_PACKET pPacket;
213 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
217 UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN];
219 ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
222 IrqState = pAd->irq_disabled;
226 // Reset is in progress, stop immediately
227 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
228 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)||
229 !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
231 Status = NDIS_STATUS_FAILURE;
235 // Check Free priority queue
236 // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing.
240 // free Tx(QueIdx) resources
241 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
245 // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870
246 NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE));
247 Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE), pData, Length);
248 if (Status != NDIS_STATUS_SUCCESS)
250 DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
254 //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
255 //pAd->CommonCfg.MlmeRate = RATE_2;
258 Status = MlmeDataHardTransmit(pAd, QueIdx, pPacket);
259 if (Status != NDIS_STATUS_SUCCESS)
260 RTMPFreeNdisPacket(pAd, pPacket);
261 retry = MAX_DATAMM_RETRY;
267 printk("retry %d\n", retry);
268 pAd->RalinkCounters.MgmtRingFullCount++;
270 if (retry >= MAX_DATAMM_RETRY)
272 DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in DataRing, MgmtRingFullCount=%ld!\n",
273 QueIdx, pAd->RalinkCounters.MgmtRingFullCount));
277 } while (retry < MAX_DATAMM_RETRY);
286 ========================================================================
289 Copy frame from waiting queue into relative ring buffer and set
290 appropriate ASIC register to kick hardware transmit function
293 pAd Pointer to our adapter
294 pBuffer Pointer to memory of outgoing frame
295 Length Size of outgoing management frame
303 IRQL = DISPATCH_LEVEL
307 ========================================================================
309 NDIS_STATUS MlmeHardTransmit(
310 IN PRTMP_ADAPTER pAd,
312 IN PNDIS_PACKET pPacket)
314 if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
317 return NDIS_STATUS_FAILURE;
320 return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
325 NDIS_STATUS MlmeDataHardTransmit(
326 IN PRTMP_ADAPTER pAd,
328 IN PNDIS_PACKET pPacket)
330 if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
333 return NDIS_STATUS_FAILURE;
337 return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
342 NDIS_STATUS MlmeHardTransmitMgmtRing(
343 IN PRTMP_ADAPTER pAd,
345 IN PNDIS_PACKET pPacket)
347 PACKET_INFO PacketInfo;
350 PHEADER_802_11 pHeader_802_11;
351 BOOLEAN bAckRequired, bInsertTimestamp;
353 PTXWI_STRUC pFirstTxWI;
354 MAC_TABLE_ENTRY *pMacEntry = NULL;
356 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
358 RTMP_SEM_LOCK(&pAd->MgmtRingLock);
361 if (pSrcBufVA == NULL)
363 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
364 return NDIS_STATUS_FAILURE;
367 // outgoing frame always wakeup PHY to prevent frame lost
368 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
369 AsicForceWakeup(pAd, TRUE);
371 pFirstTxWI = (PTXWI_STRUC)(pSrcBufVA + TXINFO_SIZE);
372 pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); //TXWI_SIZE);
374 if (pHeader_802_11->Addr1[0] & 0x01)
376 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
380 MlmeRate = pAd->CommonCfg.MlmeRate;
383 // Verify Mlme rate for a / g bands.
384 if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
387 if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
388 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
390 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
394 // Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode.
395 if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED
396 || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED
399 if (pAd->LatchRfRegs.Channel > 14)
400 pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
402 pAd->CommonCfg.MlmeTransmit.field.MODE = 0;
407 // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
408 // Snice it's been set to 0 while on MgtMacHeaderInit
409 // By the way this will cause frame to be send on PWR_SAVE failed.
411 // pHeader_802_11->FC.PwrMgmt = 0; // (pAd->StaCfg.Psm == PWR_SAVE);
413 // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
415 // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
416 if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL))
418 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
419 (pHeader_802_11->FC.SubType == SUBTYPE_ACTION))
420 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
422 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
425 bInsertTimestamp = FALSE;
426 if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
428 //Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue.
429 if ((pAd->OpMode == OPMODE_STA) && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL))
431 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
433 bAckRequired = FALSE;
435 else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
437 if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
439 bAckRequired = FALSE;
440 pHeader_802_11->Duration = 0;
445 pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
446 if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
448 bInsertTimestamp = TRUE;
453 pHeader_802_11->Sequence = pAd->Sequence++;
454 if (pAd->Sequence >0xfff)
457 // Before radar detection done, mgmt frame can not be sent but probe req
458 // Because we need to use probe req to trigger driver to send probe req in passive scan
459 if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
460 && (pAd->CommonCfg.bIEEE80211H == 1)
461 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
463 DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
464 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
465 return (NDIS_STATUS_FAILURE);
469 // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
470 // should always has only one ohysical buffer, and the whole frame size equals
471 // to the first scatter buffer size
474 // Initialize TX Descriptor
475 // For inter-frame gap, the number is for this frame and next frame
476 // For MLME rate, we will fix as 2Mb to match other vendor's implement
478 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
479 if (pMacEntry == NULL)
481 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
482 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
486 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
487 bInsertTimestamp, FALSE, bAckRequired, FALSE,
488 0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE),
489 pMacEntry->MaxHTPhyMode.field.MCS, 0,
490 (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
491 IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
494 // Now do hardware-depened kick out.
495 HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen);
497 // Make sure to release MGMT ring resource
498 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
499 return NDIS_STATUS_SUCCESS;
503 /********************************************************************************
505 New DeQueue Procedures.
507 ********************************************************************************/
509 #define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \
511 if (bIntContext == FALSE) \
512 RTMP_IRQ_LOCK((lock), IrqFlags); \
515 #define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \
517 if (bIntContext == FALSE) \
518 RTMP_IRQ_UNLOCK((lock), IrqFlags); \
522 ========================================================================
523 Tx Path design algorithm:
524 Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal),
525 Specific Packet Type. Following show the classification rule and policy for each kinds of packets.
526 Classification Rule=>
527 Multicast: (*addr1 & 0x01) == 0x01
528 Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc.
529 11N Rate : If peer support HT
530 (1).AMPDU -- If TXBA is negotiated.
531 (2).AMSDU -- If AMSDU is capable for both peer and ourself.
532 *). AMSDU can embedded in a AMPDU, but now we didn't support it.
533 (3).Normal -- Other packets which send as 11n rate.
535 B/G Rate : If peer is b/g only.
536 (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6
537 (2).Normal -- Other packets which send as b/g rate.
539 The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
541 Classified Packet Handle Rule=>
543 No ACK, //pTxBlk->bAckRequired = FALSE;
544 No WMM, //pTxBlk->bWMM = FALSE;
545 No piggyback, //pTxBlk->bPiggyBack = FALSE;
546 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
547 Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use
548 the same policy to handle it.
549 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
552 No piggyback, //pTxBlk->bPiggyBack = FALSE;
564 ========================================================================
566 static UCHAR TxPktClassification(
567 IN RTMP_ADAPTER *pAd,
568 IN PNDIS_PACKET pPacket)
570 UCHAR TxFrameType = TX_UNKOWN_FRAME;
572 MAC_TABLE_ENTRY *pMacEntry = NULL;
573 BOOLEAN bHTRate = FALSE;
575 Wcid = RTMP_GET_PACKET_WCID(pPacket);
576 if (Wcid == MCAST_WCID)
577 { // Handle for RA is Broadcast/Multicast Address.
578 return TX_MCAST_FRAME;
581 // Handle for unicast packets
582 pMacEntry = &pAd->MacTab.Content[Wcid];
583 if (RTMP_GET_PACKET_LOWRATE(pPacket))
584 { // It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame
585 TxFrameType = TX_LEGACY_FRAME;
587 else if (IS_HT_RATE(pMacEntry))
588 { // it's a 11n capable packet
590 // Depends on HTPhyMode to check if the peer support the HTRate transmission.
591 // Currently didn't support A-MSDU embedded in A-MPDU
593 if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE))
594 TxFrameType = TX_LEGACY_FRAME;
595 #ifdef UAPSD_AP_SUPPORT
596 else if (RTMP_GET_PACKET_EOSP(pPacket))
597 TxFrameType = TX_LEGACY_FRAME;
598 #endif // UAPSD_AP_SUPPORT //
599 else if((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0)
600 return TX_AMPDU_FRAME;
601 else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED))
602 return TX_AMSDU_FRAME;
604 TxFrameType = TX_LEGACY_FRAME;
607 { // it's a legacy b/g packet.
608 if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) &&
609 (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) &&
610 (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
611 { // if peer support Ralink Aggregation, we use it.
612 TxFrameType = TX_RALINK_FRAME;
616 TxFrameType = TX_LEGACY_FRAME;
620 // Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU.
621 if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) && (TxFrameType == TX_LEGACY_FRAME))
622 TxFrameType = TX_FRAG_FRAME;
628 BOOLEAN RTMP_FillTxBlkInfo(
629 IN RTMP_ADAPTER *pAd,
632 PACKET_INFO PacketInfo;
633 PNDIS_PACKET pPacket;
634 PMAC_TABLE_ENTRY pMacEntry = NULL;
636 pPacket = pTxBlk->pPacket;
637 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
639 pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket);
640 pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket);
641 pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket);
642 pTxBlk->FrameGap = IFS_HTTXOP; // ASIC determine Frame Gap
644 if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket))
645 TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame);
647 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame);
649 // Default to clear this flag
650 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS);
653 if (pTxBlk->Wcid == MCAST_WCID)
655 pTxBlk->pMacEntry = NULL;
657 #ifdef MCAST_RATE_SPECIFIC
658 PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket);
659 if (((*pDA & 0x01) == 0x01) && (*pDA != 0xff))
660 pTxBlk->pTransmit = &pAd->CommonCfg.MCastPhyMode;
662 #endif // MCAST_RATE_SPECIFIC //
663 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
666 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); // AckRequired = FALSE, when broadcast packet in Adhoc mode.
667 //TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate);
668 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag);
669 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
670 if (RTMP_GET_PACKET_MOREDATA(pPacket))
672 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
678 pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
679 pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode;
681 pMacEntry = pTxBlk->pMacEntry;
684 // For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK.
685 if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK)
686 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
688 TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired);
691 // If support WMM, enable it.
692 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
693 CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))
694 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM);
697 if (pTxBlk->TxFrameType == TX_LEGACY_FRAME)
699 if ( (RTMP_GET_PACKET_LOWRATE(pPacket)) ||
700 ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1)))
701 { // Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate.
702 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
704 // Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it???
705 if (IS_HT_STA(pTxBlk->pMacEntry) &&
706 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) &&
707 ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)))
709 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
710 TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS);
714 if ( (IS_HT_RATE(pMacEntry) == FALSE) &&
715 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE)))
716 { // Currently piggy-back only support when peer is operate in b/g mode.
717 TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack);
720 if (RTMP_GET_PACKET_MOREDATA(pPacket))
722 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
724 #ifdef UAPSD_AP_SUPPORT
725 if (RTMP_GET_PACKET_EOSP(pPacket))
727 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP);
729 #endif // UAPSD_AP_SUPPORT //
731 else if (pTxBlk->TxFrameType == TX_FRAG_FRAME)
733 TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag);
736 pMacEntry->DebugTxCount++;
748 BOOLEAN CanDoAggregateTransmit(
749 IN RTMP_ADAPTER *pAd,
750 IN NDIS_PACKET *pPacket,
754 //printk("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType);
756 if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
759 if (RTMP_GET_PACKET_DHCP(pPacket) ||
760 RTMP_GET_PACKET_EAPOL(pPacket) ||
761 RTMP_GET_PACKET_WAI(pPacket))
764 if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) &&
765 ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100)))
766 { // For AMSDU, allow the packets with total length < max-amsdu size
770 if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) &&
771 (pTxBlk->TxPacketList.Number == 2))
772 { // For RALINK-Aggregation, allow two frames in one batch.
776 if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP
784 ========================================================================
787 To do the enqueue operation and extract the first item of waiting
788 list. If a number of available shared memory segments could meet
789 the request of extracted item, the extracted item will be fragmented
790 into shared memory segments.
793 pAd Pointer to our adapter
794 pQueue Pointer to Waiting Queue
799 IRQL = DISPATCH_LEVEL
803 ========================================================================
805 VOID RTMPDeQueuePacket(
806 IN PRTMP_ADAPTER pAd,
807 IN BOOLEAN bIntContext,
808 IN UCHAR QIdx, /* BulkOutPipeId */
809 IN UCHAR Max_Tx_Packets)
811 PQUEUE_ENTRY pEntry = NULL;
812 PNDIS_PACKET pPacket;
813 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
815 PQUEUE_HEADER pQueue;
816 ULONG FreeNumber[NUM_OF_TX_RING];
817 UCHAR QueIdx, sQIdx, eQIdx;
818 unsigned long IrqFlags = 0;
819 BOOLEAN hasTxDesc = FALSE;
825 RtmpDiagStruct *pDiagStruct = &pAd->DiagStruct;
829 if (QIdx == NUM_OF_TX_RING)
832 //PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA)
833 eQIdx = 3; // 4 ACs, start from 0.
837 sQIdx = eQIdx = QIdx;
840 for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++)
844 RT28XX_START_DEQUEUE(pAd, QueIdx, IrqFlags);
847 firstRound = ((QueIdx == 0) ? TRUE : FALSE);
848 #endif // DBG_DIAGNOSE //
852 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |
853 fRTMP_ADAPTER_RADIO_OFF |
854 fRTMP_ADAPTER_RESET_IN_PROGRESS |
855 fRTMP_ADAPTER_HALT_IN_PROGRESS |
856 fRTMP_ADAPTER_NIC_NOT_EXIST))))
858 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
862 if (Count >= Max_Tx_Packets)
865 DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
866 if (&pAd->TxSwQueue[QueIdx] == NULL)
869 if (firstRound == TRUE)
870 pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][0]++;
871 #endif // DBG_DIAGNOSE //
872 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
877 // probe the Queue Head
878 pQueue = &pAd->TxSwQueue[QueIdx];
879 if ((pEntry = pQueue->Head) == NULL)
881 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
886 NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK));
887 pTxBlk->QueIdx = QueIdx;
889 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
891 // Early check to make sure we have enoguh Tx Resource.
892 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
895 pAd->PrivateInfo.TxRingFullCnt++;
897 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
902 pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
903 pEntry = RemoveHeadQueue(pQueue);
904 pTxBlk->TotalFrameNum++;
905 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
906 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
907 pTxBlk->pPacket = pPacket;
908 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
910 if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME)
912 // Enhance SW Aggregation Mechanism
913 if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType))
915 InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
916 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
921 if((pEntry = pQueue->Head) == NULL)
924 // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation.
925 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
926 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
927 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
928 if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE))
931 //Remove the packet from the TxSwQueue and insert into pTxBlk
932 pEntry = RemoveHeadQueue(pQueue);
934 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
935 pTxBlk->TotalFrameNum++;
936 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
937 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
938 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
941 if (pTxBlk->TxPacketList.Number == 1)
942 pTxBlk->TxFrameType = TX_LEGACY_FRAME;
946 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
949 Count += pTxBlk->TxPacketList.Number;
951 // Do HardTransmit now.
952 Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
955 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
959 RTUSBKickBulkOut(pAd);
967 ========================================================================
970 Calculates the duration which is required to transmit out frames
971 with given size and specified rate.
974 pAd Pointer to our adapter
976 Size Frame size in units of byte
979 Duration number in units of usec
982 IRQL = DISPATCH_LEVEL
986 ========================================================================
988 USHORT RTMPCalcDuration(
989 IN PRTMP_ADAPTER pAd,
995 if (Rate < RATE_FIRST_OFDM_RATE) // CCK
997 if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED))
998 Duration = 96; // 72+24 preamble+plcp
1000 Duration = 192; // 144+48 preamble+plcp
1002 Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]);
1003 if ((Size << 4) % RateIdTo500Kbps[Rate])
1006 else if (Rate <= RATE_LAST_OFDM_RATE)// OFDM rates
1008 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
1009 Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
1010 if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
1015 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
1018 return (USHORT)Duration;
1023 ========================================================================
1025 Routine Description:
1026 Calculates the duration which is required to transmit out frames
1027 with given size and specified rate.
1030 pTxWI Pointer to head of each MPDU to HW.
1031 Ack Setting for Ack requirement bit
1032 Fragment Setting for Fragment bit
1033 RetryMode Setting for retry mode
1034 Ifs Setting for IFS gap
1035 Rate Setting for transmit rate
1036 Service Setting for service
1038 TxPreamble Short or Long preamble when using CCK rates
1039 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1044 IRQL = PASSIVE_LEVEL
1045 IRQL = DISPATCH_LEVEL
1047 See also : BASmartHardTransmit() !!!
1049 ========================================================================
1052 IN PRTMP_ADAPTER pAd,
1053 IN PTXWI_STRUC pOutTxWI,
1056 IN BOOLEAN InsTimestamp,
1059 IN BOOLEAN NSeq, // HW new a sequence.
1068 IN HTTRANSMIT_SETTING *pTransmit)
1070 PMAC_TABLE_ENTRY pMac = NULL;
1074 if (WCID < MAX_LEN_OF_MAC_TABLE)
1075 pMac = &pAd->MacTab.Content[WCID];
1078 // Always use Long preamble before verifiation short preamble functionality works well.
1079 // Todo: remove the following line if short preamble functionality works
1081 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1082 NdisZeroMemory(&TxWI, TXWI_SIZE);
1087 pTxWI->CFACK = CFACK;
1088 pTxWI->TS= InsTimestamp;
1089 pTxWI->AMPDU = AMPDU;
1091 pTxWI->txop= Txopmode;
1094 // John tune the performace with Intel Client in 20 MHz performance
1095 BASize = pAd->CommonCfg.TxBASize;
1099 pTxWI->BAWinSize = BASize;
1100 pTxWI->ShortGI = pTransmit->field.ShortGI;
1101 pTxWI->STBC = pTransmit->field.STBC;
1103 pTxWI->WirelessCliID = WCID;
1104 pTxWI->MPDUtotalByteCount = Length;
1105 pTxWI->PacketId = PID;
1107 // If CCK or OFDM, BW must be 20
1108 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1110 pTxWI->MCS = pTransmit->field.MCS;
1111 pTxWI->PHYMODE = pTransmit->field.MODE;
1112 pTxWI->CFACK = CfAck;
1116 if (pAd->CommonCfg.bMIMOPSEnable)
1118 if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1120 // Dynamic MIMO Power Save Mode
1123 else if (pMac->MmpsMode == MMPS_STATIC)
1125 // Static MIMO Power Save Mode
1126 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1133 //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;
1134 if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled))
1136 pTxWI->MpduDensity = 7;
1140 pTxWI->MpduDensity = pMac->MpduDensity;
1144 pTxWI->PacketId = pTxWI->MCS;
1145 NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC));
1149 VOID RTMPWriteTxWI_Data(
1150 IN PRTMP_ADAPTER pAd,
1151 IN OUT PTXWI_STRUC pTxWI,
1154 HTTRANSMIT_SETTING *pTransmit;
1155 PMAC_TABLE_ENTRY pMacEntry;
1160 pTransmit = pTxBlk->pTransmit;
1161 pMacEntry = pTxBlk->pMacEntry;
1165 // Always use Long preamble before verifiation short preamble functionality works well.
1166 // Todo: remove the following line if short preamble functionality works
1168 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1169 NdisZeroMemory(pTxWI, TXWI_SIZE);
1171 pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1172 pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1173 pTxWI->txop = pTxBlk->FrameGap;
1175 pTxWI->WirelessCliID = pTxBlk->Wcid;
1177 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1178 pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
1180 // If CCK or OFDM, BW must be 20
1181 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1182 pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
1184 // John tune the performace with Intel Client in 20 MHz performance
1185 BASize = pAd->CommonCfg.TxBASize;
1186 if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry))
1188 UCHAR RABAOriIdx = 0; //The RA's BA Originator table index.
1190 RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
1191 BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1194 pTxWI->TxBF = pTransmit->field.TxBF;
1195 pTxWI->BAWinSize = BASize;
1196 pTxWI->ShortGI = pTransmit->field.ShortGI;
1197 pTxWI->STBC = pTransmit->field.STBC;
1199 pTxWI->MCS = pTransmit->field.MCS;
1200 pTxWI->PHYMODE = pTransmit->field.MODE;
1204 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1206 // Dynamic MIMO Power Save Mode
1209 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1211 // Static MIMO Power Save Mode
1212 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1219 if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled))
1221 pTxWI->MpduDensity = 7;
1225 pTxWI->MpduDensity = pMacEntry->MpduDensity;
1230 if (pTxBlk->QueIdx== 0)
1232 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1233 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1235 #endif // DBG_DIAGNOSE //
1237 // for rate adapation
1238 pTxWI->PacketId = pTxWI->MCS;
1242 VOID RTMPWriteTxWI_Cache(
1243 IN PRTMP_ADAPTER pAd,
1244 IN OUT PTXWI_STRUC pTxWI,
1247 PHTTRANSMIT_SETTING pTransmit;
1248 PMAC_TABLE_ENTRY pMacEntry;
1253 pMacEntry = pTxBlk->pMacEntry;
1254 pTransmit = pTxBlk->pTransmit;
1256 if (pMacEntry->bAutoTxRateSwitch)
1258 pTxWI->txop = IFS_HTTXOP;
1260 // If CCK or OFDM, BW must be 20
1261 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1262 pTxWI->ShortGI = pTransmit->field.ShortGI;
1263 pTxWI->STBC = pTransmit->field.STBC;
1265 pTxWI->MCS = pTransmit->field.MCS;
1266 pTxWI->PHYMODE = pTransmit->field.MODE;
1268 // set PID for TxRateSwitching
1269 pTxWI->PacketId = pTransmit->field.MCS;
1272 pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE);
1275 if (pAd->CommonCfg.bMIMOPSEnable)
1277 // MIMO Power Save Mode
1278 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1280 // Dynamic MIMO Power Save Mode
1283 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1285 // Static MIMO Power Save Mode
1286 if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7))
1295 if (pTxBlk->QueIdx== 0)
1297 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1298 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1300 #endif // DBG_DIAGNOSE //
1302 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1308 ========================================================================
1310 Routine Description:
1311 Calculates the duration which is required to transmit out frames
1312 with given size and specified rate.
1315 pTxD Pointer to transmit descriptor
1316 Ack Setting for Ack requirement bit
1317 Fragment Setting for Fragment bit
1318 RetryMode Setting for retry mode
1319 Ifs Setting for IFS gap
1320 Rate Setting for transmit rate
1321 Service Setting for service
1323 TxPreamble Short or Long preamble when using CCK rates
1324 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1329 IRQL = PASSIVE_LEVEL
1330 IRQL = DISPATCH_LEVEL
1332 ========================================================================
1334 VOID RTMPWriteTxDescriptor(
1335 IN PRTMP_ADAPTER pAd,
1341 // Always use Long preamble before verifiation short preamble functionality works well.
1342 // Todo: remove the following line if short preamble functionality works
1344 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1346 pTxD->WIV = (bWIV) ? 1: 0;
1347 pTxD->QSEL= (QueueSEL);
1348 if (pAd->bGenOneHCCA == TRUE)
1349 pTxD->QSEL= FIFO_HCCA;
1354 // should be called only when -
1355 // 1. MEADIA_CONNECTED
1356 // 2. AGGREGATION_IN_USED
1357 // 3. Fragmentation not in used
1358 // 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible
1359 BOOLEAN TxFrameIsAggregatible(
1360 IN PRTMP_ADAPTER pAd,
1361 IN PUCHAR pPrevAddr1,
1365 // can't aggregate EAPOL (802.1x) frame
1366 if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1369 // can't aggregate multicast/broadcast frame
1370 if (p8023hdr[0] & 0x01)
1373 if (INFRA_ON(pAd)) // must be unicast to AP
1375 else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA
1383 ========================================================================
1385 Routine Description:
1386 Check the MSDU Aggregation policy
1387 1.HT aggregation is A-MSDU
1388 2.legaacy rate aggregation is software aggregation by Ralink.
1396 ========================================================================
1398 BOOLEAN PeerIsAggreOn(
1399 IN PRTMP_ADAPTER pAd,
1401 IN PMAC_TABLE_ENTRY pMacEntry)
1403 ULONG AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
1405 if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags))
1407 if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX)
1412 #ifdef AGGREGATION_SUPPORT
1413 if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
1414 { // legacy Ralink Aggregation support
1417 #endif // AGGREGATION_SUPPORT //
1425 ========================================================================
1427 Routine Description:
1428 Check and fine the packet waiting in SW queue with highest priority
1431 pAd Pointer to our adapter
1434 pQueue Pointer to Waiting Queue
1436 IRQL = DISPATCH_LEVEL
1440 ========================================================================
1442 PQUEUE_HEADER RTMPCheckTxSwQueue(
1443 IN PRTMP_ADAPTER pAd,
1448 Number = pAd->TxSwQueue[QID_AC_BK].Number
1449 + pAd->TxSwQueue[QID_AC_BE].Number
1450 + pAd->TxSwQueue[QID_AC_VI].Number
1451 + pAd->TxSwQueue[QID_AC_VO].Number
1452 + pAd->TxSwQueue[QID_HCCA].Number;
1454 if (pAd->TxSwQueue[QID_AC_VO].Head != NULL)
1456 *pQueIdx = QID_AC_VO;
1457 return (&pAd->TxSwQueue[QID_AC_VO]);
1459 else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL)
1461 *pQueIdx = QID_AC_VI;
1462 return (&pAd->TxSwQueue[QID_AC_VI]);
1464 else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL)
1466 *pQueIdx = QID_AC_BE;
1467 return (&pAd->TxSwQueue[QID_AC_BE]);
1469 else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL)
1471 *pQueIdx = QID_AC_BK;
1472 return (&pAd->TxSwQueue[QID_AC_BK]);
1474 else if (pAd->TxSwQueue[QID_HCCA].Head != NULL)
1476 *pQueIdx = QID_HCCA;
1477 return (&pAd->TxSwQueue[QID_HCCA]);
1480 // No packet pending in Tx Sw queue
1481 *pQueIdx = QID_AC_BK;
1489 ========================================================================
1491 Routine Description:
1492 Suspend MSDU transmission
1495 pAd Pointer to our adapter
1502 ========================================================================
1504 VOID RTMPSuspendMsduTransmission(
1505 IN PRTMP_ADAPTER pAd)
1507 DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n"));
1511 // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
1512 // use Lowbound as R66 value on ScanNextChannel(...)
1514 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue);
1516 // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)
1517 RTMPSetAGCInitValue(pAd, BW_20);
1519 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1523 ========================================================================
1525 Routine Description:
1526 Resume MSDU transmission
1529 pAd Pointer to our adapter
1534 IRQL = DISPATCH_LEVEL
1538 ========================================================================
1540 VOID RTMPResumeMsduTransmission(
1541 IN PRTMP_ADAPTER pAd)
1543 DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
1546 // After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value
1547 // R66 should not be 0
1548 if (pAd->BbpTuning.R66CurrentValue == 0)
1550 pAd->BbpTuning.R66CurrentValue = 0x38;
1551 DBGPRINT_ERR(("RTMPResumeMsduTransmission, R66CurrentValue=0...\n"));
1554 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue);
1556 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1557 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1561 UINT deaggregate_AMSDU_announce(
1562 IN PRTMP_ADAPTER pAd,
1563 PNDIS_PACKET pPacket,
1568 USHORT SubFrameSize;
1569 PHEADER_802_3 pAMSDUsubheader;
1571 UCHAR Header802_3[14];
1573 PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP;
1574 PNDIS_PACKET pClonePacket;
1580 while (DataSize > LENGTH_802_3)
1585 pAMSDUsubheader = (PHEADER_802_3)pData;
1586 PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8);
1587 SubFrameSize = PayloadSize + LENGTH_802_3;
1590 if ((DataSize < SubFrameSize) || (PayloadSize > 1518 ))
1595 pPayload = pData + LENGTH_802_3;
1597 pSA = pData + MAC_ADDR_LEN;
1599 // convert to 802.3 header
1600 CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP);
1602 if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) )
1604 // avoid local heap overflow, use dyanamic allocation
1605 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
1606 memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize);
1607 Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize;
1608 WpaEAPOLKeyAction(pAd, Elem);
1613 if (pRemovedLLCSNAP)
1615 pPayload -= LENGTH_802_3;
1616 PayloadSize += LENGTH_802_3;
1617 NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3);
1621 pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
1624 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket));
1628 // A-MSDU has padding to multiple of 4 including subframe header.
1629 // align SubFrameSize up to multiple of 4
1630 SubFrameSize = (SubFrameSize+3)&(~0x3);
1633 if (SubFrameSize > 1528 || SubFrameSize < 32)
1638 if (DataSize > SubFrameSize)
1640 pData += SubFrameSize;
1641 DataSize -= SubFrameSize;
1650 // finally release original rx packet
1651 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1657 UINT BA_Reorder_AMSDU_Annnounce(
1658 IN PRTMP_ADAPTER pAd,
1659 IN PNDIS_PACKET pPacket)
1665 pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
1666 DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
1668 nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
1675 ==========================================================================
1677 Look up the MAC address in the MAC table. Return NULL if not found.
1679 pEntry - pointer to the MAC entry; NULL is not found
1680 ==========================================================================
1682 MAC_TABLE_ENTRY *MacTableLookup(
1683 IN PRTMP_ADAPTER pAd,
1687 MAC_TABLE_ENTRY *pEntry = NULL;
1689 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1690 pEntry = pAd->MacTab.Hash[HashIdx];
1692 while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh))
1694 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1699 pEntry = pEntry->pNext;
1705 MAC_TABLE_ENTRY *MacTableInsertEntry(
1706 IN PRTMP_ADAPTER pAd,
1709 IN BOOLEAN CleanAll)
1713 MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
1716 if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
1721 if (pAd->StaCfg.BssType == BSS_INFRA)
1724 // allocate one MAC entry
1725 NdisAcquireSpinLock(&pAd->MacTabLock);
1726 for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++) // skip entry#0 so that "entry index == AID" for fast lookup
1728 // pick up the first available vacancy
1729 if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
1730 (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
1731 (pAd->MacTab.Content[i].ValidAsApCli== FALSE) &&
1732 (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
1735 pEntry = &pAd->MacTab.Content[i];
1736 if (CleanAll == TRUE)
1738 pEntry->MaxSupportedRate = RATE_11;
1739 pEntry->CurrTxRate = RATE_11;
1740 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1741 pEntry->PairwiseKey.KeyLen = 0;
1742 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1746 pEntry->ValidAsCLI = TRUE;
1747 pEntry->ValidAsWDS = FALSE;
1748 pEntry->ValidAsApCli = FALSE;
1749 pEntry->ValidAsMesh = FALSE;
1750 pEntry->ValidAsDls = FALSE;
1754 pEntry->bIAmBadAtheros = FALSE;
1756 pEntry->CMTimerRunning = FALSE;
1757 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
1758 pEntry->RSNIE_Len = 0;
1759 NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
1760 pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
1762 if (pEntry->ValidAsMesh)
1763 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH);
1764 else if (pEntry->ValidAsApCli)
1765 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI);
1766 else if (pEntry->ValidAsWDS)
1767 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS);
1769 pEntry->apidx = apidx;
1773 pEntry->AuthMode = pAd->StaCfg.AuthMode;
1774 pEntry->WepStatus = pAd->StaCfg.WepStatus;
1775 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
1779 pEntry->GTKState = REKEY_NEGOTIATING;
1780 pEntry->PairwiseKey.KeyLen = 0;
1781 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1782 pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
1783 pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
1784 COPY_MAC_ADDR(pEntry->Addr, pAddr);
1785 pEntry->Sst = SST_NOT_AUTH;
1786 pEntry->AuthState = AS_NOT_AUTH;
1787 pEntry->Aid = (USHORT)i; //0;
1788 pEntry->CapabilityInfo = 0;
1789 pEntry->PsMode = PWR_ACTIVE;
1790 pEntry->PsQIdleCount = 0;
1791 pEntry->NoDataIdleCount = 0;
1792 pEntry->ContinueTxFailCnt = 0;
1793 InitializeQueueHeader(&pEntry->PsQueue);
1796 pAd->MacTab.Size ++;
1797 // Add this entry into ASIC RX WCID search table
1798 RT28XX_STA_ENTRY_ADD(pAd, pEntry);
1800 DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size));
1805 // add this MAC entry into HASH table
1808 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1809 if (pAd->MacTab.Hash[HashIdx] == NULL)
1811 pAd->MacTab.Hash[HashIdx] = pEntry;
1815 pCurrEntry = pAd->MacTab.Hash[HashIdx];
1816 while (pCurrEntry->pNext != NULL)
1817 pCurrEntry = pCurrEntry->pNext;
1818 pCurrEntry->pNext = pEntry;
1822 NdisReleaseSpinLock(&pAd->MacTabLock);
1827 ==========================================================================
1829 Delete a specified client from MAC table
1830 ==========================================================================
1832 BOOLEAN MacTableDeleteEntry(
1833 IN PRTMP_ADAPTER pAd,
1838 MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
1841 if (wcid >= MAX_LEN_OF_MAC_TABLE)
1844 NdisAcquireSpinLock(&pAd->MacTabLock);
1846 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1847 pEntry = &pAd->MacTab.Content[wcid];
1849 if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh
1852 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1855 // Delete this entry from ASIC on-chip WCID Table
1856 RT28XX_STA_ENTRY_MAC_RESET(pAd, wcid);
1858 // free resources of BA
1859 BASessionTearDownALL(pAd, pEntry->Aid);
1862 pProbeEntry = pAd->MacTab.Hash[HashIdx];
1863 ASSERT(pProbeEntry);
1868 if (pProbeEntry == pEntry)
1870 if (pPrevEntry == NULL)
1872 pAd->MacTab.Hash[HashIdx] = pEntry->pNext;
1876 pPrevEntry->pNext = pEntry->pNext;
1881 pPrevEntry = pProbeEntry;
1882 pProbeEntry = pProbeEntry->pNext;
1883 } while (pProbeEntry);
1886 ASSERT(pProbeEntry != NULL);
1888 RT28XX_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
1891 if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
1893 RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
1894 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
1898 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1899 pAd->MacTab.Size --;
1900 DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size));
1904 printk("\n%s: Impossible Wcid = %d !!!!!\n", __func__, wcid);
1908 NdisReleaseSpinLock(&pAd->MacTabLock);
1910 //Reset operating mode when no Sta.
1911 if (pAd->MacTab.Size == 0)
1913 pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
1915 AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/);
1918 RT28XX_UPDATE_PROTECT(pAd); // edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet
1927 ==========================================================================
1929 This routine reset the entire MAC table. All packets pending in
1930 the power-saving queues are freed here.
1931 ==========================================================================
1934 IN PRTMP_ADAPTER pAd)
1938 DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
1939 //NdisAcquireSpinLock(&pAd->MacTabLock);
1941 for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
1943 if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
1945 // free resources of BA
1946 BASessionTearDownALL(pAd, i);
1948 pAd->MacTab.Content[i].ValidAsCLI = FALSE;
1953 NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6);
1954 RT28XX_STA_ENTRY_MAC_RESET(pAd, i);
1957 //AsicDelWcidTab(pAd, i);
1965 ==========================================================================
1968 IRQL = DISPATCH_LEVEL
1970 ==========================================================================
1973 IN PRTMP_ADAPTER pAd,
1974 IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
1976 IN USHORT CapabilityInfo,
1978 IN USHORT ListenIntv)
1980 COPY_MAC_ADDR(AssocReq->Addr, pAddr);
1981 // Add mask to support 802.11b mode only
1982 AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request
1983 AssocReq->Timeout = Timeout;
1984 AssocReq->ListenIntv = ListenIntv;
1989 ==========================================================================
1992 IRQL = DISPATCH_LEVEL
1994 ==========================================================================
1996 VOID DisassocParmFill(
1997 IN PRTMP_ADAPTER pAd,
1998 IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
2002 COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
2003 DisassocReq->Reason = Reason;
2008 ========================================================================
2010 Routine Description:
2011 Check the out going frame, if this is an DHCP or ARP datagram
2012 will be duplicate another frame at low data rate transmit.
2015 pAd Pointer to our adapter
2016 pPacket Pointer to outgoing Ndis frame
2019 TRUE To be duplicate at Low data rate transmit. (1mb)
2022 IRQL = DISPATCH_LEVEL
2026 MAC header + IP Header + UDP Header
2030 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
2032 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
2035 port 0x43 means Bootstrap Protocol, server.
2036 Port 0x44 means Bootstrap Protocol, client.
2038 ========================================================================
2041 BOOLEAN RTMPCheckDHCPFrame(
2042 IN PRTMP_ADAPTER pAd,
2043 IN PNDIS_PACKET pPacket)
2045 PACKET_INFO PacketInfo;
2046 ULONG NumberOfBytesRead = 0;
2047 ULONG CurrentOffset = 0;
2048 PVOID pVirtualAddress = NULL;
2049 UINT NdisBufferLength;
2052 UCHAR ByteOffset36 = 0;
2053 UCHAR ByteOffset38 = 0;
2054 BOOLEAN ReadFirstParm = TRUE;
2056 RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength);
2058 NumberOfBytesRead += NdisBufferLength;
2059 pSrc = (PUCHAR) pVirtualAddress;
2060 Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
2063 // Check DHCP & BOOTP protocol
2065 while (NumberOfBytesRead <= PacketInfo.TotalPacketLength)
2067 if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE))
2069 CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength);
2070 ByteOffset36 = *(pSrc + CurrentOffset);
2071 ReadFirstParm = FALSE;
2074 if (NumberOfBytesRead >= 37)
2076 CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength);
2077 ByteOffset38 = *(pSrc + CurrentOffset);
2084 // Check for DHCP & BOOTP protocol
2085 if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43))
2088 // 2054 (hex 0806) for ARP datagrams
2089 // if this packet is not ARP datagrams, then do nothing
2090 // ARP datagrams will also be duplicate at 1mb broadcast frames
2092 if (Protocol != 0x0806 )
2100 BOOLEAN RTMPCheckEtherType(
2101 IN PRTMP_ADAPTER pAd,
2102 IN PNDIS_PACKET pPacket)
2108 UINT16 srcPort, dstPort;
2109 BOOLEAN status = TRUE;
2112 pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
2113 pktLen = GET_OS_PKT_LEN(pPacket);
2117 RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
2119 // get Ethernet protocol field
2120 TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13];
2122 pSrcBuf += LENGTH_802_3; // Skip the Ethernet Header.
2124 if (TypeLen <= 1500)
2125 { // 802.3, 802.3 LLC
2127 DestMAC(6) + SrcMAC(6) + Lenght(2) +
2128 DSAP(1) + SSAP(1) + Control(1) +
2129 if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
2130 => + SNAP (5, OriginationID(3) + etherType(2))
2132 if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03)
2134 Sniff2BytesFromNdisBuffer(pSrcBuf, 6, &Byte0, &Byte1);
2135 RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
2136 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2137 pSrcBuf += 8; // Skip this LLC/SNAP header
2141 //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.
2145 // If it's a VLAN packet, get the real Type/Length field.
2146 if (TypeLen == 0x8100)
2148 /* 0x8100 means VLAN packets */
2150 /* Dest. MAC Address (6-bytes) +
2151 Source MAC Address (6-bytes) +
2152 Length/Type = 802.1Q Tag Type (2-byte) +
2153 Tag Control Information (2-bytes) +
2154 Length / Type (2-bytes) +
2155 data payload (0-n bytes) +
2157 Frame Check Sequence (4-bytes) */
2159 RTMP_SET_PACKET_VLAN(pPacket, 1);
2160 Sniff2BytesFromNdisBuffer(pSrcBuf, 2, &Byte0, &Byte1);
2161 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2163 pSrcBuf += 4; // Skip the VLAN Header.
2170 ASSERT((pktLen > 34));
2171 if (*(pSrcBuf + 9) == 0x11)
2173 ASSERT((pktLen > 34)); // 14 for ethernet header, 20 for IP header
2175 pSrcBuf += 20; // Skip the IP header
2176 srcPort = OS_NTOHS(*((UINT16 *)pSrcBuf));
2177 dstPort = OS_NTOHS(*((UINT16 *)(pSrcBuf +2)));
2179 if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44))
2180 { //It's a BOOTP/DHCP packet
2181 RTMP_SET_PACKET_DHCP(pPacket, 1);
2189 RTMP_SET_PACKET_DHCP(pPacket, 1);
2195 RTMP_SET_PACKET_EAPOL(pPacket, 1);
2209 VOID Update_Rssi_Sample(
2210 IN PRTMP_ADAPTER pAd,
2211 IN RSSI_SAMPLE *pRssi,
2212 IN PRXWI_STRUC pRxWI)
2214 CHAR rssi0 = pRxWI->RSSI0;
2215 CHAR rssi1 = pRxWI->RSSI1;
2216 CHAR rssi2 = pRxWI->RSSI2;
2220 pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0);
2221 pRssi->AvgRssi0X8 = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
2222 pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
2227 pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1);
2228 pRssi->AvgRssi1X8 = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
2229 pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
2234 pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2);
2235 pRssi->AvgRssi2X8 = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
2236 pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
2242 // Normal legacy Rx packet indication
2243 VOID Indicate_Legacy_Packet(
2244 IN PRTMP_ADAPTER pAd,
2246 IN UCHAR FromWhichBSSID)
2248 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2249 UCHAR Header802_3[LENGTH_802_3];
2251 // 1. get 802.3 Header
2253 // a. pointer pRxBlk->pData to payload
2254 // b. modify pRxBlk->DataSize
2255 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2257 if (pRxBlk->DataSize > MAX_RX_PKT_LEN)
2261 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2266 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
2269 if (pAd->CommonCfg.bDisableReordering == 0)
2271 PBA_REC_ENTRY pBAEntry;
2273 UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID;
2274 UCHAR TID = pRxBlk->pRxWI->TID;
2277 #define REORDERING_PACKET_TIMEOUT ((100 * HZ)/1000) // system ticks -- 100 ms
2279 if (Wcid < MAX_LEN_OF_MAC_TABLE)
2281 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
2284 pBAEntry = &pAd->BATable.BARecEntry[Idx];
2285 // update last rx time
2286 NdisGetSystemUpTime(&Now32);
2287 if ((pBAEntry->list.qlen > 0) &&
2288 RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
2291 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);
2292 hex_dump("Dump the legacy Packet:", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), 64);
2293 ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
2300 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2303 // pass this 802.3 packet to upper layer or forward this packet to WM directly
2305 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
2309 // Normal, AMPDU or AMSDU
2310 VOID CmmRxnonRalinkFrameIndicate(
2311 IN PRTMP_ADAPTER pAd,
2313 IN UCHAR FromWhichBSSID)
2315 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
2317 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2321 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
2324 Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2328 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
2334 VOID CmmRxRalinkFrameIndicate(
2335 IN PRTMP_ADAPTER pAd,
2336 IN MAC_TABLE_ENTRY *pEntry,
2338 IN UCHAR FromWhichBSSID)
2340 UCHAR Header802_3[LENGTH_802_3];
2342 UINT16 Payload1Size, Payload2Size;
2344 PNDIS_PACKET pPacket2 = NULL;
2348 Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8);
2350 if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize))
2352 /* skip two byte MSDU2 len */
2354 pRxBlk->DataSize -= 2;
2359 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2363 // get 802.3 Header and remove LLC
2364 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2366 ASSERT(pRxBlk->pRxPacket);
2368 // Ralink Aggregation frame
2369 pAd->RalinkCounters.OneSecRxAggregationCount ++;
2370 Payload1Size = pRxBlk->DataSize - Msdu2Size;
2371 Payload2Size = Msdu2Size - LENGTH_802_3;
2373 pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
2375 pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID);
2380 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2384 // update payload size of 1st packet
2385 pRxBlk->DataSize = Payload1Size;
2386 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2388 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID);
2392 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
2397 #define RESET_FRAGFRAME(_fragFrame) \
2399 _fragFrame.RxSize = 0; \
2400 _fragFrame.Sequence = 0; \
2401 _fragFrame.LastFrag = 0; \
2402 _fragFrame.Flags = 0; \
2406 PNDIS_PACKET RTMPDeFragmentDataFrame(
2407 IN PRTMP_ADAPTER pAd,
2410 PHEADER_802_11 pHeader = pRxBlk->pHeader;
2411 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2412 UCHAR *pData = pRxBlk->pData;
2413 USHORT DataSize = pRxBlk->DataSize;
2414 PNDIS_PACKET pRetPacket = NULL;
2415 UCHAR *pFragBuffer = NULL;
2416 BOOLEAN bReassDone = FALSE;
2417 UCHAR HeaderRoom = 0;
2422 HeaderRoom = pData - (UCHAR *)pHeader;
2424 // Re-assemble the fragmented packets
2425 if (pHeader->Frag == 0) // Frag. Number is 0 : First frag or only one pkt
2427 // the first pkt of fragment, record it.
2428 if (pHeader->FC.MoreFrag)
2430 ASSERT(pAd->FragFrame.pFragPacket);
2431 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2432 pAd->FragFrame.RxSize = DataSize + HeaderRoom;
2433 NdisMoveMemory(pFragBuffer, pHeader, pAd->FragFrame.RxSize);
2434 pAd->FragFrame.Sequence = pHeader->Sequence;
2435 pAd->FragFrame.LastFrag = pHeader->Frag; // Should be 0
2436 ASSERT(pAd->FragFrame.LastFrag == 0);
2437 goto done; // end of processing this frame
2440 else //Middle & End of fragment
2442 if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
2443 (pHeader->Frag != (pAd->FragFrame.LastFrag + 1)))
2445 // Fragment is not the same sequence or out of fragment number order
2446 // Reset Fragment control blk
2447 RESET_FRAGFRAME(pAd->FragFrame);
2448 DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n"));
2449 goto done; // give up this frame
2451 else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE)
2453 // Fragment frame is too large, it exeeds the maximum frame size.
2454 // Reset Fragment control blk
2455 RESET_FRAGFRAME(pAd->FragFrame);
2456 DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
2457 goto done; // give up this frame
2461 // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.
2462 // In this case, we will dropt it.
2464 if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H)))
2466 DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag));
2467 goto done; // give up this frame
2470 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2472 // concatenate this fragment into the re-assembly buffer
2473 NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize);
2474 pAd->FragFrame.RxSize += DataSize;
2475 pAd->FragFrame.LastFrag = pHeader->Frag; // Update fragment number
2478 if (pHeader->FC.MoreFrag == FALSE)
2485 // always release rx fragmented packet
2486 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2488 // return defragmented packet if packet is reassembled completely
2489 // otherwise return NULL
2492 PNDIS_PACKET pNewFragPacket;
2494 // allocate a new packet buffer for fragment
2495 pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
2499 pRetPacket = pAd->FragFrame.pFragPacket;
2500 pAd->FragFrame.pFragPacket = pNewFragPacket;
2501 pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
2502 pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom;
2503 pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
2504 pRxBlk->pRxPacket = pRetPacket;
2508 RESET_FRAGFRAME(pAd->FragFrame);
2516 VOID Indicate_AMSDU_Packet(
2517 IN PRTMP_ADAPTER pAd,
2519 IN UCHAR FromWhichBSSID)
2523 update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
2524 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
2525 nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize);
2528 VOID Indicate_EAPOL_Packet(
2529 IN PRTMP_ADAPTER pAd,
2531 IN UCHAR FromWhichBSSID)
2533 MAC_TABLE_ENTRY *pEntry = NULL;
2536 pEntry = &pAd->MacTab.Content[BSSID_WCID];
2537 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
2543 DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
2545 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2550 #define BCN_TBTT_OFFSET 64 //defer 64 us
2551 VOID ReSyncBeaconTime(
2552 IN PRTMP_ADAPTER pAd)
2558 Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
2560 pAd->TbttTickCount++;
2563 // The updated BeaconInterval Value will affect Beacon Interval after two TBTT
2564 // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
2566 if (Offset == (BCN_TBTT_OFFSET-2))
2568 BCN_TIME_CFG_STRUC csr;
2569 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2570 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; // ASIC register in units of 1/16 TU = 64us
2571 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2575 if (Offset == (BCN_TBTT_OFFSET-1))
2577 BCN_TIME_CFG_STRUC csr;
2579 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2580 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU
2581 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);