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));
180 ========================================================================
183 Copy frame from waiting queue into relative ring buffer and set
184 appropriate ASIC register to kick hardware transmit function
187 pAd Pointer to our adapter
188 pBuffer Pointer to memory of outgoing frame
189 Length Size of outgoing management frame
197 IRQL = DISPATCH_LEVEL
201 ========================================================================
203 NDIS_STATUS MlmeHardTransmit(
204 IN PRTMP_ADAPTER pAd,
206 IN PNDIS_PACKET pPacket)
208 if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
211 return NDIS_STATUS_FAILURE;
214 return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
220 NDIS_STATUS MlmeHardTransmitMgmtRing(
221 IN PRTMP_ADAPTER pAd,
223 IN PNDIS_PACKET pPacket)
225 PACKET_INFO PacketInfo;
228 PHEADER_802_11 pHeader_802_11;
229 BOOLEAN bAckRequired, bInsertTimestamp;
231 PTXWI_STRUC pFirstTxWI;
232 MAC_TABLE_ENTRY *pMacEntry = NULL;
234 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
236 // Make sure MGMT ring resource won't be used by other threads
237 // sample, for IRQ LOCK -> SEM LOCK
238 // IrqState = pAd->irq_disabled;
240 RTMP_SEM_LOCK(&pAd->MgmtRingLock);
243 if (pSrcBufVA == NULL)
245 // The buffer shouldn't be NULL
247 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
248 return NDIS_STATUS_FAILURE;
251 #ifdef CONFIG_STA_SUPPORT
252 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
254 // outgoing frame always wakeup PHY to prevent frame lost
255 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
256 AsicForceWakeup(pAd, TRUE);
258 #endif // CONFIG_STA_SUPPORT //
260 pFirstTxWI = (PTXWI_STRUC)(pSrcBufVA + TXINFO_SIZE);
261 pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); //TXWI_SIZE);
263 if (pHeader_802_11->Addr1[0] & 0x01)
265 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
269 MlmeRate = pAd->CommonCfg.MlmeRate;
272 // Verify Mlme rate for a / g bands.
273 if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
276 if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
277 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
279 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
282 #ifdef CONFIG_STA_SUPPORT
283 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
285 // Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode.
286 if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED
287 #ifdef DOT11_N_SUPPORT
288 || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED
289 #endif // DOT11_N_SUPPORT //
292 if (pAd->LatchRfRegs.Channel > 14)
293 pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
295 pAd->CommonCfg.MlmeTransmit.field.MODE = 0;
298 #endif // CONFIG_STA_SUPPORT //
301 // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
302 // Snice it's been set to 0 while on MgtMacHeaderInit
303 // By the way this will cause frame to be send on PWR_SAVE failed.
305 // pHeader_802_11->FC.PwrMgmt = 0; // (pAd->StaCfg.Psm == PWR_SAVE);
307 // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
308 #ifdef CONFIG_STA_SUPPORT
309 // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
310 if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL))
312 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
313 (pHeader_802_11->FC.SubType == SUBTYPE_ACTION))
314 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
316 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
318 #endif // CONFIG_STA_SUPPORT //
320 bInsertTimestamp = FALSE;
321 if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
323 #ifdef CONFIG_STA_SUPPORT
324 //Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue.
325 if ((pAd->OpMode == OPMODE_STA) && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL))
327 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
329 #endif // CONFIG_STA_SUPPORT //
330 bAckRequired = FALSE;
332 else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
335 //pHeader_802_11->Sequence = pAd->Sequence;
337 if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
339 bAckRequired = FALSE;
340 pHeader_802_11->Duration = 0;
345 pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
346 if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
348 bInsertTimestamp = TRUE;
353 pHeader_802_11->Sequence = pAd->Sequence++;
354 if (pAd->Sequence >0xfff)
357 // Before radar detection done, mgmt frame can not be sent but probe req
358 // Because we need to use probe req to trigger driver to send probe req in passive scan
359 if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
360 && (pAd->CommonCfg.bIEEE80211H == 1)
361 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
363 DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
365 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
366 return (NDIS_STATUS_FAILURE);
370 RTMPFrameEndianChange(pAd, (PUCHAR)pHeader_802_11, DIR_WRITE, FALSE);
374 // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
375 // should always has only one ohysical buffer, and the whole frame size equals
376 // to the first scatter buffer size
379 // Initialize TX Descriptor
380 // For inter-frame gap, the number is for this frame and next frame
381 // For MLME rate, we will fix as 2Mb to match other vendor's implement
382 // pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
384 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
385 if (pMacEntry == NULL)
387 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
388 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
392 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
393 bInsertTimestamp, FALSE, bAckRequired, FALSE,
394 0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE),
395 pMacEntry->MaxHTPhyMode.field.MCS, 0,
396 (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
397 IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
401 RTMPWIEndianChange((PUCHAR)pFirstTxWI, TYPE_TXWI);
404 // Now do hardware-depened kick out.
405 HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen);
407 // Make sure to release MGMT ring resource
409 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
410 return NDIS_STATUS_SUCCESS;
414 /********************************************************************************
416 New DeQueue Procedures.
418 ********************************************************************************/
420 #define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \
422 if (bIntContext == FALSE) \
423 RTMP_IRQ_LOCK((lock), IrqFlags); \
426 #define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \
428 if (bIntContext == FALSE) \
429 RTMP_IRQ_UNLOCK((lock), IrqFlags); \
434 static VOID dumpTxBlk(TX_BLK *pTxBlk)
436 NDIS_PACKET *pPacket;
438 PQUEUE_ENTRY pQEntry;
440 printk("Dump TX_BLK Structure:\n");
441 printk("\tTxFrameType=%d!\n", pTxBlk->TxFrameType);
442 printk("\tTotalFrameLen=%d\n", pTxBlk->TotalFrameLen);
443 printk("\tTotalFrameNum=%ld!\n", pTxBlk->TxPacketList.Number);
444 printk("\tTotalFragNum=%d!\n", pTxBlk->TotalFragNum);
445 printk("\tpPacketList=\n");
447 frameNum = pTxBlk->TxPacketList.Number;
449 for(i=0; i < frameNum; i++)
453 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
454 pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
457 pBuf = GET_OS_PKT_DATAPTR(pPacket);
458 printk("\t\t[%d]:ptr=0x%x, Len=%d!\n", i, (UINT32)(GET_OS_PKT_DATAPTR(pPacket)), GET_OS_PKT_LEN(pPacket));
460 for (j =0 ; j < GET_OS_PKT_LEN(pPacket); j++)
462 printk("%02x ", (pBuf[j] & 0xff));
466 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
469 printk("\tWcid=%d!\n", pTxBlk->Wcid);
470 printk("\tapidx=%d!\n", pTxBlk->apidx);
471 printk("----EndOfDump\n");
478 ========================================================================
479 Tx Path design algorithm:
480 Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal),
481 Specific Packet Type. Following show the classification rule and policy for each kinds of packets.
482 Classification Rule=>
483 Multicast: (*addr1 & 0x01) == 0x01
484 Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc.
485 11N Rate : If peer support HT
486 (1).AMPDU -- If TXBA is negotiated.
487 (2).AMSDU -- If AMSDU is capable for both peer and ourself.
488 *). AMSDU can embedded in a AMPDU, but now we didn't support it.
489 (3).Normal -- Other packets which send as 11n rate.
491 B/G Rate : If peer is b/g only.
492 (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6
493 (2).Normal -- Other packets which send as b/g rate.
495 The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
497 Classified Packet Handle Rule=>
499 No ACK, //pTxBlk->bAckRequired = FALSE;
500 No WMM, //pTxBlk->bWMM = FALSE;
501 No piggyback, //pTxBlk->bPiggyBack = FALSE;
502 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
503 Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use
504 the same policy to handle it.
505 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
508 No piggyback, //pTxBlk->bPiggyBack = FALSE;
520 ========================================================================
522 static UCHAR TxPktClassification(
523 IN RTMP_ADAPTER *pAd,
524 IN PNDIS_PACKET pPacket)
526 UCHAR TxFrameType = TX_UNKOWN_FRAME;
528 MAC_TABLE_ENTRY *pMacEntry = NULL;
529 #ifdef DOT11_N_SUPPORT
530 BOOLEAN bHTRate = FALSE;
531 #endif // DOT11_N_SUPPORT //
533 Wcid = RTMP_GET_PACKET_WCID(pPacket);
534 if (Wcid == MCAST_WCID)
535 { // Handle for RA is Broadcast/Multicast Address.
536 return TX_MCAST_FRAME;
539 // Handle for unicast packets
540 pMacEntry = &pAd->MacTab.Content[Wcid];
541 if (RTMP_GET_PACKET_LOWRATE(pPacket))
542 { // It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame
543 TxFrameType = TX_LEGACY_FRAME;
545 #ifdef DOT11_N_SUPPORT
546 else if (IS_HT_RATE(pMacEntry))
547 { // it's a 11n capable packet
549 // Depends on HTPhyMode to check if the peer support the HTRate transmission.
550 // Currently didn't support A-MSDU embedded in A-MPDU
552 if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE))
553 TxFrameType = TX_LEGACY_FRAME;
554 #ifdef UAPSD_AP_SUPPORT
555 else if (RTMP_GET_PACKET_EOSP(pPacket))
556 TxFrameType = TX_LEGACY_FRAME;
557 #endif // UAPSD_AP_SUPPORT //
558 else if((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0)
559 return TX_AMPDU_FRAME;
560 else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED))
561 return TX_AMSDU_FRAME;
563 TxFrameType = TX_LEGACY_FRAME;
565 #endif // DOT11_N_SUPPORT //
567 { // it's a legacy b/g packet.
568 if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) &&
569 (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) &&
570 (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
571 { // if peer support Ralink Aggregation, we use it.
572 TxFrameType = TX_RALINK_FRAME;
576 TxFrameType = TX_LEGACY_FRAME;
580 // Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU.
581 if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) && (TxFrameType == TX_LEGACY_FRAME))
582 TxFrameType = TX_FRAG_FRAME;
588 BOOLEAN RTMP_FillTxBlkInfo(
589 IN RTMP_ADAPTER *pAd,
592 PACKET_INFO PacketInfo;
593 PNDIS_PACKET pPacket;
594 PMAC_TABLE_ENTRY pMacEntry = NULL;
596 pPacket = pTxBlk->pPacket;
597 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
599 pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket);
600 pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket);
601 pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket);
602 pTxBlk->FrameGap = IFS_HTTXOP; // ASIC determine Frame Gap
604 if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket))
605 TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame);
607 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame);
609 // Default to clear this flag
610 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS);
613 if (pTxBlk->Wcid == MCAST_WCID)
615 pTxBlk->pMacEntry = NULL;
617 #ifdef MCAST_RATE_SPECIFIC
618 PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket);
619 if (((*pDA & 0x01) == 0x01) && (*pDA != 0xff))
620 pTxBlk->pTransmit = &pAd->CommonCfg.MCastPhyMode;
622 #endif // MCAST_RATE_SPECIFIC //
623 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
626 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); // AckRequired = FALSE, when broadcast packet in Adhoc mode.
627 //TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate);
628 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag);
629 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
630 if (RTMP_GET_PACKET_MOREDATA(pPacket))
632 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
638 pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
639 pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode;
641 pMacEntry = pTxBlk->pMacEntry;
644 // For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK.
645 if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK)
646 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
648 TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired);
652 #ifdef CONFIG_STA_SUPPORT
653 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
656 // If support WMM, enable it.
657 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
658 CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))
659 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM);
661 #endif // CONFIG_STA_SUPPORT //
664 if (pTxBlk->TxFrameType == TX_LEGACY_FRAME)
666 if ( (RTMP_GET_PACKET_LOWRATE(pPacket)) ||
667 ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1)))
668 { // Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate.
669 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
670 #ifdef DOT11_N_SUPPORT
671 // Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it???
672 if (IS_HT_STA(pTxBlk->pMacEntry) &&
673 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) &&
674 ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)))
676 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
677 TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS);
679 #endif // DOT11_N_SUPPORT //
682 #ifdef DOT11_N_SUPPORT
683 if ( (IS_HT_RATE(pMacEntry) == FALSE) &&
684 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE)))
685 { // Currently piggy-back only support when peer is operate in b/g mode.
686 TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack);
688 #endif // DOT11_N_SUPPORT //
690 if (RTMP_GET_PACKET_MOREDATA(pPacket))
692 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
694 #ifdef UAPSD_AP_SUPPORT
695 if (RTMP_GET_PACKET_EOSP(pPacket))
697 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP);
699 #endif // UAPSD_AP_SUPPORT //
701 else if (pTxBlk->TxFrameType == TX_FRAG_FRAME)
703 TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag);
706 pMacEntry->DebugTxCount++;
713 BOOLEAN CanDoAggregateTransmit(
714 IN RTMP_ADAPTER *pAd,
715 IN NDIS_PACKET *pPacket,
719 //printk("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType);
721 if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
724 if (RTMP_GET_PACKET_DHCP(pPacket) ||
725 RTMP_GET_PACKET_EAPOL(pPacket) ||
726 RTMP_GET_PACKET_WAI(pPacket))
729 if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) &&
730 ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100)))
731 { // For AMSDU, allow the packets with total length < max-amsdu size
735 if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) &&
736 (pTxBlk->TxPacketList.Number == 2))
737 { // For RALINK-Aggregation, allow two frames in one batch.
741 #ifdef CONFIG_STA_SUPPORT
742 if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP
745 #endif // CONFIG_STA_SUPPORT //
752 ========================================================================
755 To do the enqueue operation and extract the first item of waiting
756 list. If a number of available shared memory segments could meet
757 the request of extracted item, the extracted item will be fragmented
758 into shared memory segments.
761 pAd Pointer to our adapter
762 pQueue Pointer to Waiting Queue
767 IRQL = DISPATCH_LEVEL
771 ========================================================================
773 VOID RTMPDeQueuePacket(
774 IN PRTMP_ADAPTER pAd,
775 IN BOOLEAN bIntContext,
776 IN UCHAR QIdx, /* BulkOutPipeId */
777 IN UCHAR Max_Tx_Packets)
779 PQUEUE_ENTRY pEntry = NULL;
780 PNDIS_PACKET pPacket;
781 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
783 PQUEUE_HEADER pQueue;
784 ULONG FreeNumber[NUM_OF_TX_RING];
785 UCHAR QueIdx, sQIdx, eQIdx;
786 unsigned long IrqFlags = 0;
787 BOOLEAN hasTxDesc = FALSE;
793 RtmpDiagStruct *pDiagStruct = &pAd->DiagStruct;
797 if (QIdx == NUM_OF_TX_RING)
800 eQIdx = 3; // 4 ACs, start from 0.
804 sQIdx = eQIdx = QIdx;
807 for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++)
811 RT28XX_START_DEQUEUE(pAd, QueIdx, IrqFlags);
814 firstRound = ((QueIdx == 0) ? TRUE : FALSE);
815 #endif // DBG_DIAGNOSE //
819 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |
820 fRTMP_ADAPTER_RADIO_OFF |
821 fRTMP_ADAPTER_RESET_IN_PROGRESS |
822 fRTMP_ADAPTER_HALT_IN_PROGRESS |
823 fRTMP_ADAPTER_NIC_NOT_EXIST))))
825 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
829 if (Count >= Max_Tx_Packets)
832 DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
833 if (&pAd->TxSwQueue[QueIdx] == NULL)
836 if (firstRound == TRUE)
837 pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][0]++;
838 #endif // DBG_DIAGNOSE //
839 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
844 // probe the Queue Head
845 pQueue = &pAd->TxSwQueue[QueIdx];
846 if ((pEntry = pQueue->Head) == NULL)
848 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
853 NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK));
854 //InitializeQueueHeader(&pTxBlk->TxPacketList); // Didn't need it because we already memzero it.
855 pTxBlk->QueIdx = QueIdx;
857 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
859 // Early check to make sure we have enoguh Tx Resource.
860 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
863 pAd->PrivateInfo.TxRingFullCnt++;
865 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
870 pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
871 pEntry = RemoveHeadQueue(pQueue);
872 pTxBlk->TotalFrameNum++;
873 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
874 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
875 pTxBlk->pPacket = pPacket;
876 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
878 if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME)
880 // Enhance SW Aggregation Mechanism
881 if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType))
883 InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
884 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
889 if((pEntry = pQueue->Head) == NULL)
892 // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation.
893 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
894 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
895 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
896 if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE))
899 //Remove the packet from the TxSwQueue and insert into pTxBlk
900 pEntry = RemoveHeadQueue(pQueue);
902 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
903 pTxBlk->TotalFrameNum++;
904 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
905 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
906 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
909 if (pTxBlk->TxPacketList.Number == 1)
910 pTxBlk->TxFrameType = TX_LEGACY_FRAME;
914 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
917 Count += pTxBlk->TxPacketList.Number;
919 // Do HardTransmit now.
920 #ifdef CONFIG_STA_SUPPORT
921 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
922 Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
923 #endif // CONFIG_STA_SUPPORT //
926 #if 0 // We should not break if HardTransmit failed. Well, at least now we should not!
927 if (Status != NDIS_STATUS_SUCCESS)
929 DBGPRINT(RT_DEBUG_TRACE /*RT_DEBUG_INFO*/,("RTMPHardTransmit return failed!!!\n"));
935 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
939 RTUSBKickBulkOut(pAd);
947 ========================================================================
950 Calculates the duration which is required to transmit out frames
951 with given size and specified rate.
954 pAd Pointer to our adapter
956 Size Frame size in units of byte
959 Duration number in units of usec
962 IRQL = DISPATCH_LEVEL
966 ========================================================================
968 USHORT RTMPCalcDuration(
969 IN PRTMP_ADAPTER pAd,
975 if (Rate < RATE_FIRST_OFDM_RATE) // CCK
977 if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED))
978 Duration = 96; // 72+24 preamble+plcp
980 Duration = 192; // 144+48 preamble+plcp
982 Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]);
983 if ((Size << 4) % RateIdTo500Kbps[Rate])
986 else if (Rate <= RATE_LAST_OFDM_RATE)// OFDM rates
988 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
989 Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
990 if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
995 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
998 return (USHORT)Duration;
1003 ========================================================================
1005 Routine Description:
1006 Calculates the duration which is required to transmit out frames
1007 with given size and specified rate.
1010 pTxWI Pointer to head of each MPDU to HW.
1011 Ack Setting for Ack requirement bit
1012 Fragment Setting for Fragment bit
1013 RetryMode Setting for retry mode
1014 Ifs Setting for IFS gap
1015 Rate Setting for transmit rate
1016 Service Setting for service
1018 TxPreamble Short or Long preamble when using CCK rates
1019 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1024 IRQL = PASSIVE_LEVEL
1025 IRQL = DISPATCH_LEVEL
1027 See also : BASmartHardTransmit() !!!
1029 ========================================================================
1032 IN PRTMP_ADAPTER pAd,
1033 IN PTXWI_STRUC pOutTxWI,
1036 IN BOOLEAN InsTimestamp,
1039 IN BOOLEAN NSeq, // HW new a sequence.
1048 IN HTTRANSMIT_SETTING *pTransmit)
1050 PMAC_TABLE_ENTRY pMac = NULL;
1054 if (WCID < MAX_LEN_OF_MAC_TABLE)
1055 pMac = &pAd->MacTab.Content[WCID];
1058 // Always use Long preamble before verifiation short preamble functionality works well.
1059 // Todo: remove the following line if short preamble functionality works
1061 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1062 NdisZeroMemory(&TxWI, TXWI_SIZE);
1067 pTxWI->CFACK = CFACK;
1068 pTxWI->TS= InsTimestamp;
1069 pTxWI->AMPDU = AMPDU;
1071 pTxWI->txop= Txopmode;
1074 // John tune the performace with Intel Client in 20 MHz performance
1075 #ifdef DOT11_N_SUPPORT
1076 BASize = pAd->CommonCfg.TxBASize;
1080 pTxWI->BAWinSize = BASize;
1081 pTxWI->ShortGI = pTransmit->field.ShortGI;
1082 pTxWI->STBC = pTransmit->field.STBC;
1083 #endif // DOT11_N_SUPPORT //
1085 pTxWI->WirelessCliID = WCID;
1086 pTxWI->MPDUtotalByteCount = Length;
1087 pTxWI->PacketId = PID;
1089 // If CCK or OFDM, BW must be 20
1090 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1091 #ifdef DOT11N_DRAFT3
1093 pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1094 #endif // DOT11N_DRAFT3 //
1096 pTxWI->MCS = pTransmit->field.MCS;
1097 pTxWI->PHYMODE = pTransmit->field.MODE;
1098 pTxWI->CFACK = CfAck;
1100 #ifdef DOT11_N_SUPPORT
1103 if (pAd->CommonCfg.bMIMOPSEnable)
1105 if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1107 // Dynamic MIMO Power Save Mode
1110 else if (pMac->MmpsMode == MMPS_STATIC)
1112 // Static MIMO Power Save Mode
1113 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1120 //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;
1121 if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled))
1123 pTxWI->MpduDensity = 7;
1127 pTxWI->MpduDensity = pMac->MpduDensity;
1130 #endif // DOT11_N_SUPPORT //
1132 pTxWI->PacketId = pTxWI->MCS;
1133 NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC));
1137 VOID RTMPWriteTxWI_Data(
1138 IN PRTMP_ADAPTER pAd,
1139 IN OUT PTXWI_STRUC pTxWI,
1142 HTTRANSMIT_SETTING *pTransmit;
1143 PMAC_TABLE_ENTRY pMacEntry;
1144 #ifdef DOT11_N_SUPPORT
1146 #endif // DOT11_N_SUPPORT //
1151 pTransmit = pTxBlk->pTransmit;
1152 pMacEntry = pTxBlk->pMacEntry;
1156 // Always use Long preamble before verifiation short preamble functionality works well.
1157 // Todo: remove the following line if short preamble functionality works
1159 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1160 NdisZeroMemory(pTxWI, TXWI_SIZE);
1162 pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1163 pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1164 pTxWI->txop = pTxBlk->FrameGap;
1166 pTxWI->WirelessCliID = pTxBlk->Wcid;
1168 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1169 pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
1171 // If CCK or OFDM, BW must be 20
1172 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1173 #ifdef DOT11_N_SUPPORT
1174 #ifdef DOT11N_DRAFT3
1176 pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1177 #endif // DOT11N_DRAFT3 //
1178 pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
1180 // John tune the performace with Intel Client in 20 MHz performance
1181 BASize = pAd->CommonCfg.TxBASize;
1182 if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry))
1184 UCHAR RABAOriIdx = 0; //The RA's BA Originator table index.
1186 RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
1187 BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1195 pTxWI->TxBF = pTransmit->field.TxBF;
1196 pTxWI->BAWinSize = BASize;
1197 pTxWI->ShortGI = pTransmit->field.ShortGI;
1198 pTxWI->STBC = pTransmit->field.STBC;
1199 #endif // DOT11_N_SUPPORT //
1201 pTxWI->MCS = pTransmit->field.MCS;
1202 pTxWI->PHYMODE = pTransmit->field.MODE;
1204 #ifdef DOT11_N_SUPPORT
1207 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1209 // Dynamic MIMO Power Save Mode
1212 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1214 // Static MIMO Power Save Mode
1215 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1222 if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled))
1224 pTxWI->MpduDensity = 7;
1228 pTxWI->MpduDensity = pMacEntry->MpduDensity;
1231 #endif // DOT11_N_SUPPORT //
1234 if (pTxBlk->QueIdx== 0)
1236 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1237 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1239 #endif // DBG_DIAGNOSE //
1241 // for rate adapation
1242 pTxWI->PacketId = pTxWI->MCS;
1246 VOID RTMPWriteTxWI_Cache(
1247 IN PRTMP_ADAPTER pAd,
1248 IN OUT PTXWI_STRUC pTxWI,
1251 PHTTRANSMIT_SETTING /*pTxHTPhyMode,*/ pTransmit;
1252 PMAC_TABLE_ENTRY pMacEntry;
1257 pMacEntry = pTxBlk->pMacEntry;
1258 pTransmit = pTxBlk->pTransmit;
1260 if (pMacEntry->bAutoTxRateSwitch)
1262 pTxWI->txop = IFS_HTTXOP;
1264 // If CCK or OFDM, BW must be 20
1265 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1266 pTxWI->ShortGI = pTransmit->field.ShortGI;
1267 pTxWI->STBC = pTransmit->field.STBC;
1269 pTxWI->MCS = pTransmit->field.MCS;
1270 pTxWI->PHYMODE = pTransmit->field.MODE;
1272 // set PID for TxRateSwitching
1273 pTxWI->PacketId = pTransmit->field.MCS;
1276 #ifdef DOT11_N_SUPPORT
1277 pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE);
1280 #ifdef DOT11N_DRAFT3
1282 pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1283 #endif // DOT11N_DRAFT3 //
1285 if (pAd->CommonCfg.bMIMOPSEnable)
1287 // MIMO Power Save Mode
1288 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1290 // Dynamic MIMO Power Save Mode
1293 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1295 // Static MIMO Power Save Mode
1296 if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7))
1303 #endif // DOT11_N_SUPPORT //
1306 if (pTxBlk->QueIdx== 0)
1308 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1309 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1311 #endif // DBG_DIAGNOSE //
1313 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1319 ========================================================================
1321 Routine Description:
1322 Calculates the duration which is required to transmit out frames
1323 with given size and specified rate.
1326 pTxD Pointer to transmit descriptor
1327 Ack Setting for Ack requirement bit
1328 Fragment Setting for Fragment bit
1329 RetryMode Setting for retry mode
1330 Ifs Setting for IFS gap
1331 Rate Setting for transmit rate
1332 Service Setting for service
1334 TxPreamble Short or Long preamble when using CCK rates
1335 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1340 IRQL = PASSIVE_LEVEL
1341 IRQL = DISPATCH_LEVEL
1343 ========================================================================
1345 VOID RTMPWriteTxDescriptor(
1346 IN PRTMP_ADAPTER pAd,
1352 // Always use Long preamble before verifiation short preamble functionality works well.
1353 // Todo: remove the following line if short preamble functionality works
1355 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1357 pTxD->WIV = (bWIV) ? 1: 0;
1358 pTxD->QSEL= (QueueSEL);
1359 //RT2860c?? fixed using EDCA queue for test... We doubt Queue1 has problem. 2006-09-26 Jan
1360 //pTxD->QSEL= FIFO_EDCA;
1361 if (pAd->bGenOneHCCA == TRUE)
1362 pTxD->QSEL= FIFO_HCCA;
1367 // should be called only when -
1368 // 1. MEADIA_CONNECTED
1369 // 2. AGGREGATION_IN_USED
1370 // 3. Fragmentation not in used
1371 // 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible
1372 BOOLEAN TxFrameIsAggregatible(
1373 IN PRTMP_ADAPTER pAd,
1374 IN PUCHAR pPrevAddr1,
1378 // can't aggregate EAPOL (802.1x) frame
1379 if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1382 // can't aggregate multicast/broadcast frame
1383 if (p8023hdr[0] & 0x01)
1386 if (INFRA_ON(pAd)) // must be unicast to AP
1388 else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA
1396 ========================================================================
1398 Routine Description:
1399 Check the MSDU Aggregation policy
1400 1.HT aggregation is A-MSDU
1401 2.legaacy rate aggregation is software aggregation by Ralink.
1409 ========================================================================
1411 BOOLEAN PeerIsAggreOn(
1412 IN PRTMP_ADAPTER pAd,
1414 IN PMAC_TABLE_ENTRY pMacEntry)
1416 ULONG AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
1418 if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags))
1420 #ifdef DOT11_N_SUPPORT
1421 if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX)
1425 #endif // DOT11_N_SUPPORT //
1427 #ifdef AGGREGATION_SUPPORT
1428 if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
1429 { // legacy Ralink Aggregation support
1432 #endif // AGGREGATION_SUPPORT //
1440 ========================================================================
1442 Routine Description:
1443 Check and fine the packet waiting in SW queue with highest priority
1446 pAd Pointer to our adapter
1449 pQueue Pointer to Waiting Queue
1451 IRQL = DISPATCH_LEVEL
1455 ========================================================================
1457 PQUEUE_HEADER RTMPCheckTxSwQueue(
1458 IN PRTMP_ADAPTER pAd,
1463 // 2004-11-15 to be removed. test aggregation only
1464 // if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2))
1467 Number = pAd->TxSwQueue[QID_AC_BK].Number
1468 + pAd->TxSwQueue[QID_AC_BE].Number
1469 + pAd->TxSwQueue[QID_AC_VI].Number
1470 + pAd->TxSwQueue[QID_AC_VO].Number
1471 + pAd->TxSwQueue[QID_HCCA].Number;
1473 if (pAd->TxSwQueue[QID_AC_VO].Head != NULL)
1475 *pQueIdx = QID_AC_VO;
1476 return (&pAd->TxSwQueue[QID_AC_VO]);
1478 else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL)
1480 *pQueIdx = QID_AC_VI;
1481 return (&pAd->TxSwQueue[QID_AC_VI]);
1483 else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL)
1485 *pQueIdx = QID_AC_BE;
1486 return (&pAd->TxSwQueue[QID_AC_BE]);
1488 else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL)
1490 *pQueIdx = QID_AC_BK;
1491 return (&pAd->TxSwQueue[QID_AC_BK]);
1493 else if (pAd->TxSwQueue[QID_HCCA].Head != NULL)
1495 *pQueIdx = QID_HCCA;
1496 return (&pAd->TxSwQueue[QID_HCCA]);
1499 // No packet pending in Tx Sw queue
1500 *pQueIdx = QID_AC_BK;
1508 ========================================================================
1510 Routine Description:
1511 Suspend MSDU transmission
1514 pAd Pointer to our adapter
1521 ========================================================================
1523 VOID RTMPSuspendMsduTransmission(
1524 IN PRTMP_ADAPTER pAd)
1526 DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n"));
1530 // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
1531 // use Lowbound as R66 value on ScanNextChannel(...)
1533 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue);
1535 // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)
1536 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd)));
1537 RTMPSetAGCInitValue(pAd, BW_20);
1539 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1540 //RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000); // abort all TX rings
1545 ========================================================================
1547 Routine Description:
1548 Resume MSDU transmission
1551 pAd Pointer to our adapter
1556 IRQL = DISPATCH_LEVEL
1560 ========================================================================
1562 VOID RTMPResumeMsduTransmission(
1563 IN PRTMP_ADAPTER pAd)
1567 DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
1570 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue);
1572 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1573 // sample, for IRQ LOCK to SEM LOCK
1574 // IrqState = pAd->irq_disabled;
1576 // RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1578 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1582 UINT deaggregate_AMSDU_announce(
1583 IN PRTMP_ADAPTER pAd,
1584 PNDIS_PACKET pPacket,
1589 USHORT SubFrameSize;
1590 PHEADER_802_3 pAMSDUsubheader;
1592 UCHAR Header802_3[14];
1594 PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP;
1595 PNDIS_PACKET pClonePacket;
1601 while (DataSize > LENGTH_802_3)
1606 //hex_dump("subheader", pData, 64);
1607 pAMSDUsubheader = (PHEADER_802_3)pData;
1608 //pData += LENGTH_802_3;
1609 PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8);
1610 SubFrameSize = PayloadSize + LENGTH_802_3;
1613 if ((DataSize < SubFrameSize) || (PayloadSize > 1518 ))
1618 //printk("%d subframe: Size = %d\n", nMSDU, PayloadSize);
1620 pPayload = pData + LENGTH_802_3;
1622 pSA = pData + MAC_ADDR_LEN;
1624 // convert to 802.3 header
1625 CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP);
1627 #ifdef CONFIG_STA_SUPPORT
1628 if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) )
1630 // avoid local heap overflow, use dyanamic allocation
1631 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
1632 memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize);
1633 Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize;
1634 WpaEAPOLKeyAction(pAd, Elem);
1637 #endif // CONFIG_STA_SUPPORT //
1639 #ifdef CONFIG_STA_SUPPORT
1640 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1642 if (pRemovedLLCSNAP)
1644 pPayload -= LENGTH_802_3;
1645 PayloadSize += LENGTH_802_3;
1646 NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3);
1649 #endif // CONFIG_STA_SUPPORT //
1651 pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
1654 #ifdef CONFIG_STA_SUPPORT
1655 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1656 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket));
1657 #endif // CONFIG_STA_SUPPORT //
1661 // A-MSDU has padding to multiple of 4 including subframe header.
1662 // align SubFrameSize up to multiple of 4
1663 SubFrameSize = (SubFrameSize+3)&(~0x3);
1666 if (SubFrameSize > 1528 || SubFrameSize < 32)
1671 if (DataSize > SubFrameSize)
1673 pData += SubFrameSize;
1674 DataSize -= SubFrameSize;
1683 // finally release original rx packet
1684 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1690 UINT BA_Reorder_AMSDU_Annnounce(
1691 IN PRTMP_ADAPTER pAd,
1692 IN PNDIS_PACKET pPacket)
1698 pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
1699 DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
1701 nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
1708 ==========================================================================
1710 Look up the MAC address in the MAC table. Return NULL if not found.
1712 pEntry - pointer to the MAC entry; NULL is not found
1713 ==========================================================================
1715 MAC_TABLE_ENTRY *MacTableLookup(
1716 IN PRTMP_ADAPTER pAd,
1720 MAC_TABLE_ENTRY *pEntry = NULL;
1722 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1723 pEntry = pAd->MacTab.Hash[HashIdx];
1725 while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh))
1727 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1732 pEntry = pEntry->pNext;
1738 MAC_TABLE_ENTRY *MacTableInsertEntry(
1739 IN PRTMP_ADAPTER pAd,
1742 IN BOOLEAN CleanAll)
1746 MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
1749 if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
1753 #ifdef CONFIG_STA_SUPPORT
1754 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1755 if (pAd->StaCfg.BssType == BSS_INFRA)
1757 #endif // CONFIG_STA_SUPPORT //
1759 // allocate one MAC entry
1760 NdisAcquireSpinLock(&pAd->MacTabLock);
1761 for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++) // skip entry#0 so that "entry index == AID" for fast lookup
1763 // pick up the first available vacancy
1764 if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
1765 (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
1766 (pAd->MacTab.Content[i].ValidAsApCli== FALSE) &&
1767 (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
1770 pEntry = &pAd->MacTab.Content[i];
1771 if (CleanAll == TRUE)
1773 pEntry->MaxSupportedRate = RATE_11;
1774 pEntry->CurrTxRate = RATE_11;
1775 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1776 pEntry->PairwiseKey.KeyLen = 0;
1777 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1781 #ifdef CONFIG_STA_SUPPORT
1782 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1784 pEntry->ValidAsCLI = TRUE;
1785 pEntry->ValidAsWDS = FALSE;
1786 pEntry->ValidAsApCli = FALSE;
1787 pEntry->ValidAsMesh = FALSE;
1788 pEntry->ValidAsDls = FALSE;
1790 #endif // CONFIG_STA_SUPPORT //
1793 pEntry->bIAmBadAtheros = FALSE;
1795 pEntry->CMTimerRunning = FALSE;
1796 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
1797 pEntry->RSNIE_Len = 0;
1798 NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
1799 pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
1801 if (pEntry->ValidAsMesh)
1802 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH);
1803 else if (pEntry->ValidAsApCli)
1804 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI);
1805 else if (pEntry->ValidAsWDS)
1806 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS);
1808 pEntry->apidx = apidx;
1812 #ifdef CONFIG_STA_SUPPORT
1813 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1815 pEntry->AuthMode = pAd->StaCfg.AuthMode;
1816 pEntry->WepStatus = pAd->StaCfg.WepStatus;
1817 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
1819 #endif // CONFIG_STA_SUPPORT //
1822 pEntry->GTKState = REKEY_NEGOTIATING;
1823 pEntry->PairwiseKey.KeyLen = 0;
1824 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1825 pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
1826 pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
1827 COPY_MAC_ADDR(pEntry->Addr, pAddr);
1828 pEntry->Sst = SST_NOT_AUTH;
1829 pEntry->AuthState = AS_NOT_AUTH;
1830 pEntry->Aid = (USHORT)i; //0;
1831 pEntry->CapabilityInfo = 0;
1832 pEntry->PsMode = PWR_ACTIVE;
1833 pEntry->PsQIdleCount = 0;
1834 pEntry->NoDataIdleCount = 0;
1835 pEntry->ContinueTxFailCnt = 0;
1836 InitializeQueueHeader(&pEntry->PsQueue);
1839 pAd->MacTab.Size ++;
1840 // Add this entry into ASIC RX WCID search table
1841 RT28XX_STA_ENTRY_ADD(pAd, pEntry);
1843 DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size));
1848 // add this MAC entry into HASH table
1851 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1852 if (pAd->MacTab.Hash[HashIdx] == NULL)
1854 pAd->MacTab.Hash[HashIdx] = pEntry;
1858 pCurrEntry = pAd->MacTab.Hash[HashIdx];
1859 while (pCurrEntry->pNext != NULL)
1860 pCurrEntry = pCurrEntry->pNext;
1861 pCurrEntry->pNext = pEntry;
1865 NdisReleaseSpinLock(&pAd->MacTabLock);
1870 ==========================================================================
1872 Delete a specified client from MAC table
1873 ==========================================================================
1875 BOOLEAN MacTableDeleteEntry(
1876 IN PRTMP_ADAPTER pAd,
1881 MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
1883 //USHORT offset; // unused variable
1884 //UCHAR j; // unused variable
1886 if (wcid >= MAX_LEN_OF_MAC_TABLE)
1889 NdisAcquireSpinLock(&pAd->MacTabLock);
1891 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1892 //pEntry = pAd->MacTab.Hash[HashIdx];
1893 pEntry = &pAd->MacTab.Content[wcid];
1895 if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh
1898 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1901 // Delete this entry from ASIC on-chip WCID Table
1902 RT28XX_STA_ENTRY_MAC_RESET(pAd, wcid);
1904 #ifdef DOT11_N_SUPPORT
1905 // free resources of BA
1906 BASessionTearDownALL(pAd, pEntry->Aid);
1907 #endif // DOT11_N_SUPPORT //
1911 pProbeEntry = pAd->MacTab.Hash[HashIdx];
1912 ASSERT(pProbeEntry);
1917 if (pProbeEntry == pEntry)
1919 if (pPrevEntry == NULL)
1921 pAd->MacTab.Hash[HashIdx] = pEntry->pNext;
1925 pPrevEntry->pNext = pEntry->pNext;
1930 pPrevEntry = pProbeEntry;
1931 pProbeEntry = pProbeEntry->pNext;
1932 } while (pProbeEntry);
1935 ASSERT(pProbeEntry != NULL);
1937 RT28XX_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
1940 if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
1942 RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
1943 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
1947 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1948 pAd->MacTab.Size --;
1949 DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size));
1953 printk("\n%s: Impossible Wcid = %d !!!!!\n", __func__, wcid);
1957 NdisReleaseSpinLock(&pAd->MacTabLock);
1959 //Reset operating mode when no Sta.
1960 if (pAd->MacTab.Size == 0)
1962 #ifdef DOT11_N_SUPPORT
1963 pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
1964 #endif // DOT11_N_SUPPORT //
1965 AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/);
1973 ==========================================================================
1975 This routine reset the entire MAC table. All packets pending in
1976 the power-saving queues are freed here.
1977 ==========================================================================
1980 IN PRTMP_ADAPTER pAd)
1984 DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
1985 //NdisAcquireSpinLock(&pAd->MacTabLock);
1987 for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
1989 if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
1992 #ifdef DOT11_N_SUPPORT
1993 // free resources of BA
1994 BASessionTearDownALL(pAd, i);
1995 #endif // DOT11_N_SUPPORT //
1997 pAd->MacTab.Content[i].ValidAsCLI = FALSE;
2002 NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6);
2003 RT28XX_STA_ENTRY_MAC_RESET(pAd, i);
2006 //AsicDelWcidTab(pAd, i);
2014 ==========================================================================
2017 IRQL = DISPATCH_LEVEL
2019 ==========================================================================
2022 IN PRTMP_ADAPTER pAd,
2023 IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
2025 IN USHORT CapabilityInfo,
2027 IN USHORT ListenIntv)
2029 COPY_MAC_ADDR(AssocReq->Addr, pAddr);
2030 // Add mask to support 802.11b mode only
2031 AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request
2032 AssocReq->Timeout = Timeout;
2033 AssocReq->ListenIntv = ListenIntv;
2038 ==========================================================================
2041 IRQL = DISPATCH_LEVEL
2043 ==========================================================================
2045 VOID DisassocParmFill(
2046 IN PRTMP_ADAPTER pAd,
2047 IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
2051 COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
2052 DisassocReq->Reason = Reason;
2057 ========================================================================
2059 Routine Description:
2060 Check the out going frame, if this is an DHCP or ARP datagram
2061 will be duplicate another frame at low data rate transmit.
2064 pAd Pointer to our adapter
2065 pPacket Pointer to outgoing Ndis frame
2068 TRUE To be duplicate at Low data rate transmit. (1mb)
2071 IRQL = DISPATCH_LEVEL
2075 MAC header + IP Header + UDP Header
2079 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
2081 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
2084 port 0x43 means Bootstrap Protocol, server.
2085 Port 0x44 means Bootstrap Protocol, client.
2087 ========================================================================
2090 BOOLEAN RTMPCheckDHCPFrame(
2091 IN PRTMP_ADAPTER pAd,
2092 IN PNDIS_PACKET pPacket)
2094 PACKET_INFO PacketInfo;
2095 ULONG NumberOfBytesRead = 0;
2096 ULONG CurrentOffset = 0;
2097 PVOID pVirtualAddress = NULL;
2098 UINT NdisBufferLength;
2101 UCHAR ByteOffset36 = 0;
2102 UCHAR ByteOffset38 = 0;
2103 BOOLEAN ReadFirstParm = TRUE;
2105 RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength);
2107 NumberOfBytesRead += NdisBufferLength;
2108 pSrc = (PUCHAR) pVirtualAddress;
2109 Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
2112 // Check DHCP & BOOTP protocol
2114 while (NumberOfBytesRead <= PacketInfo.TotalPacketLength)
2116 if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE))
2118 CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength);
2119 ByteOffset36 = *(pSrc + CurrentOffset);
2120 ReadFirstParm = FALSE;
2123 if (NumberOfBytesRead >= 37)
2125 CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength);
2126 ByteOffset38 = *(pSrc + CurrentOffset);
2133 // Check for DHCP & BOOTP protocol
2134 if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43))
2137 // 2054 (hex 0806) for ARP datagrams
2138 // if this packet is not ARP datagrams, then do nothing
2139 // ARP datagrams will also be duplicate at 1mb broadcast frames
2141 if (Protocol != 0x0806 )
2149 BOOLEAN RTMPCheckEtherType(
2150 IN PRTMP_ADAPTER pAd,
2151 IN PNDIS_PACKET pPacket)
2157 UINT16 srcPort, dstPort;
2158 BOOLEAN status = TRUE;
2161 pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
2162 pktLen = GET_OS_PKT_LEN(pPacket);
2166 RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
2168 // get Ethernet protocol field
2169 TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13];
2171 pSrcBuf += LENGTH_802_3; // Skip the Ethernet Header.
2173 if (TypeLen <= 1500)
2174 { // 802.3, 802.3 LLC
2176 DestMAC(6) + SrcMAC(6) + Lenght(2) +
2177 DSAP(1) + SSAP(1) + Control(1) +
2178 if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
2179 => + SNAP (5, OriginationID(3) + etherType(2))
2181 if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03)
2183 Sniff2BytesFromNdisBuffer(pSrcBuf, 6, &Byte0, &Byte1);
2184 RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
2185 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2186 pSrcBuf += 8; // Skip this LLC/SNAP header
2190 //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.
2194 // If it's a VLAN packet, get the real Type/Length field.
2195 if (TypeLen == 0x8100)
2197 /* 0x8100 means VLAN packets */
2199 /* Dest. MAC Address (6-bytes) +
2200 Source MAC Address (6-bytes) +
2201 Length/Type = 802.1Q Tag Type (2-byte) +
2202 Tag Control Information (2-bytes) +
2203 Length / Type (2-bytes) +
2204 data payload (0-n bytes) +
2206 Frame Check Sequence (4-bytes) */
2208 RTMP_SET_PACKET_VLAN(pPacket, 1);
2209 Sniff2BytesFromNdisBuffer(pSrcBuf, 2, &Byte0, &Byte1);
2210 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2212 pSrcBuf += 4; // Skip the VLAN Header.
2219 ASSERT((pktLen > 34));
2220 if (*(pSrcBuf + 9) == 0x11)
2222 ASSERT((pktLen > 34)); // 14 for ethernet header, 20 for IP header
2224 pSrcBuf += 20; // Skip the IP header
2225 srcPort = OS_NTOHS(*((UINT16 *)pSrcBuf));
2226 dstPort = OS_NTOHS(*((UINT16 *)(pSrcBuf +2)));
2228 if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44))
2229 { //It's a BOOTP/DHCP packet
2230 RTMP_SET_PACKET_DHCP(pPacket, 1);
2238 RTMP_SET_PACKET_DHCP(pPacket, 1);
2244 RTMP_SET_PACKET_EAPOL(pPacket, 1);
2258 VOID Update_Rssi_Sample(
2259 IN PRTMP_ADAPTER pAd,
2260 IN RSSI_SAMPLE *pRssi,
2261 IN PRXWI_STRUC pRxWI)
2263 CHAR rssi0 = pRxWI->RSSI0;
2264 CHAR rssi1 = pRxWI->RSSI1;
2265 CHAR rssi2 = pRxWI->RSSI2;
2269 pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0);
2270 pRssi->AvgRssi0X8 = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
2271 pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
2276 pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1);
2277 pRssi->AvgRssi1X8 = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
2278 pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
2283 pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2);
2284 pRssi->AvgRssi2X8 = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
2285 pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
2291 // Normal legacy Rx packet indication
2292 VOID Indicate_Legacy_Packet(
2293 IN PRTMP_ADAPTER pAd,
2295 IN UCHAR FromWhichBSSID)
2297 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2298 UCHAR Header802_3[LENGTH_802_3];
2300 // 1. get 802.3 Header
2302 // a. pointer pRxBlk->pData to payload
2303 // b. modify pRxBlk->DataSize
2304 #ifdef CONFIG_STA_SUPPORT
2305 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2306 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2307 #endif // CONFIG_STA_SUPPORT //
2309 if (pRxBlk->DataSize > MAX_RX_PKT_LEN)
2311 #if 0 // sample take off, for multiple card design
2312 static int err_size;
2317 printk("Legacy DataSize = %d\n", pRxBlk->DataSize);
2318 hex_dump("802.3 Header", Header802_3, LENGTH_802_3);
2319 hex_dump("Payload", pRxBlk->pData, 64);
2325 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2330 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
2333 #ifdef DOT11_N_SUPPORT
2334 if (pAd->CommonCfg.bDisableReordering == 0)
2336 PBA_REC_ENTRY pBAEntry;
2338 UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID;
2339 UCHAR TID = pRxBlk->pRxWI->TID;
2342 #define REORDERING_PACKET_TIMEOUT ((100 * HZ)/1000) // system ticks -- 100 ms
2344 if (Wcid < MAX_LEN_OF_MAC_TABLE)
2346 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
2349 pBAEntry = &pAd->BATable.BARecEntry[Idx];
2350 // update last rx time
2351 NdisGetSystemUpTime(&Now32);
2352 if ((pBAEntry->list.qlen > 0) &&
2353 RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
2356 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);
2357 hex_dump("Dump the legacy Packet:", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), 64);
2358 ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
2363 #endif // DOT11_N_SUPPORT //
2366 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2369 // pass this 802.3 packet to upper layer or forward this packet to WM directly
2371 #ifdef CONFIG_STA_SUPPORT
2372 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2373 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
2374 #endif // CONFIG_STA_SUPPORT //
2379 // Normal, AMPDU or AMSDU
2380 VOID CmmRxnonRalinkFrameIndicate(
2381 IN PRTMP_ADAPTER pAd,
2383 IN UCHAR FromWhichBSSID)
2385 #ifdef DOT11_N_SUPPORT
2386 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
2388 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2391 #endif // DOT11_N_SUPPORT //
2393 #ifdef DOT11_N_SUPPORT
2394 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
2397 Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2400 #endif // DOT11_N_SUPPORT //
2402 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
2408 VOID CmmRxRalinkFrameIndicate(
2409 IN PRTMP_ADAPTER pAd,
2410 IN MAC_TABLE_ENTRY *pEntry,
2412 IN UCHAR FromWhichBSSID)
2414 UCHAR Header802_3[LENGTH_802_3];
2416 UINT16 Payload1Size, Payload2Size;
2418 PNDIS_PACKET pPacket2 = NULL;
2422 Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8);
2424 if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize))
2426 /* skip two byte MSDU2 len */
2428 pRxBlk->DataSize -= 2;
2433 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2437 // get 802.3 Header and remove LLC
2438 #ifdef CONFIG_STA_SUPPORT
2439 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2440 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2441 #endif // CONFIG_STA_SUPPORT //
2444 ASSERT(pRxBlk->pRxPacket);
2446 // Ralink Aggregation frame
2447 pAd->RalinkCounters.OneSecRxAggregationCount ++;
2448 Payload1Size = pRxBlk->DataSize - Msdu2Size;
2449 Payload2Size = Msdu2Size - LENGTH_802_3;
2451 pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
2452 #ifdef CONFIG_STA_SUPPORT
2453 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2454 pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID);
2455 #endif // CONFIG_STA_SUPPORT //
2460 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2464 // update payload size of 1st packet
2465 pRxBlk->DataSize = Payload1Size;
2466 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2468 #ifdef CONFIG_STA_SUPPORT
2469 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2470 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID);
2471 #endif // CONFIG_STA_SUPPORT //
2475 #ifdef CONFIG_STA_SUPPORT
2476 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2477 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
2478 #endif // CONFIG_STA_SUPPORT //
2483 #define RESET_FRAGFRAME(_fragFrame) \
2485 _fragFrame.RxSize = 0; \
2486 _fragFrame.Sequence = 0; \
2487 _fragFrame.LastFrag = 0; \
2488 _fragFrame.Flags = 0; \
2492 PNDIS_PACKET RTMPDeFragmentDataFrame(
2493 IN PRTMP_ADAPTER pAd,
2496 PHEADER_802_11 pHeader = pRxBlk->pHeader;
2497 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2498 UCHAR *pData = pRxBlk->pData;
2499 USHORT DataSize = pRxBlk->DataSize;
2500 PNDIS_PACKET pRetPacket = NULL;
2501 UCHAR *pFragBuffer = NULL;
2502 BOOLEAN bReassDone = FALSE;
2503 UCHAR HeaderRoom = 0;
2508 HeaderRoom = pData - (UCHAR *)pHeader;
2510 // Re-assemble the fragmented packets
2511 if (pHeader->Frag == 0) // Frag. Number is 0 : First frag or only one pkt
2513 // the first pkt of fragment, record it.
2514 if (pHeader->FC.MoreFrag)
2516 ASSERT(pAd->FragFrame.pFragPacket);
2517 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2518 pAd->FragFrame.RxSize = DataSize + HeaderRoom;
2519 NdisMoveMemory(pFragBuffer, pHeader, pAd->FragFrame.RxSize);
2520 pAd->FragFrame.Sequence = pHeader->Sequence;
2521 pAd->FragFrame.LastFrag = pHeader->Frag; // Should be 0
2522 ASSERT(pAd->FragFrame.LastFrag == 0);
2523 goto done; // end of processing this frame
2526 else //Middle & End of fragment
2528 if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
2529 (pHeader->Frag != (pAd->FragFrame.LastFrag + 1)))
2531 // Fragment is not the same sequence or out of fragment number order
2532 // Reset Fragment control blk
2533 RESET_FRAGFRAME(pAd->FragFrame);
2534 DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n"));
2535 goto done; // give up this frame
2537 else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE)
2539 // Fragment frame is too large, it exeeds the maximum frame size.
2540 // Reset Fragment control blk
2541 RESET_FRAGFRAME(pAd->FragFrame);
2542 DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
2543 goto done; // give up this frame
2547 // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.
2548 // In this case, we will dropt it.
2550 if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H)))
2552 DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag));
2553 goto done; // give up this frame
2556 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2558 // concatenate this fragment into the re-assembly buffer
2559 NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize);
2560 pAd->FragFrame.RxSize += DataSize;
2561 pAd->FragFrame.LastFrag = pHeader->Frag; // Update fragment number
2564 if (pHeader->FC.MoreFrag == FALSE)
2571 // always release rx fragmented packet
2572 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2574 // return defragmented packet if packet is reassembled completely
2575 // otherwise return NULL
2578 PNDIS_PACKET pNewFragPacket;
2580 // allocate a new packet buffer for fragment
2581 pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
2585 pRetPacket = pAd->FragFrame.pFragPacket;
2586 pAd->FragFrame.pFragPacket = pNewFragPacket;
2587 pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
2588 pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom;
2589 pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
2590 pRxBlk->pRxPacket = pRetPacket;
2594 RESET_FRAGFRAME(pAd->FragFrame);
2602 VOID Indicate_AMSDU_Packet(
2603 IN PRTMP_ADAPTER pAd,
2605 IN UCHAR FromWhichBSSID)
2609 update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
2610 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
2611 nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize);
2614 VOID Indicate_EAPOL_Packet(
2615 IN PRTMP_ADAPTER pAd,
2617 IN UCHAR FromWhichBSSID)
2619 MAC_TABLE_ENTRY *pEntry = NULL;
2622 #ifdef CONFIG_STA_SUPPORT
2623 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2625 pEntry = &pAd->MacTab.Content[BSSID_WCID];
2626 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
2629 #endif // CONFIG_STA_SUPPORT //
2633 DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
2635 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2640 #define BCN_TBTT_OFFSET 64 //defer 64 us
2641 VOID ReSyncBeaconTime(
2642 IN PRTMP_ADAPTER pAd)
2648 Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
2650 pAd->TbttTickCount++;
2653 // The updated BeaconInterval Value will affect Beacon Interval after two TBTT
2654 // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
2656 if (Offset == (BCN_TBTT_OFFSET-2))
2658 BCN_TIME_CFG_STRUC csr;
2659 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2660 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; // ASIC register in units of 1/16 TU = 64us
2661 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2665 if (Offset == (BCN_TBTT_OFFSET-1))
2667 BCN_TIME_CFG_STRUC csr;
2669 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2670 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU
2671 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);