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;
108 unsigned long IrqFlags = 0;
110 UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN];
112 ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
118 IrqState = pAd->irq_disabled;
120 if ((pAd->MACVersion == 0x28600100) && (!IrqState))
121 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
125 // Reset is in progress, stop immediately
126 if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
127 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)||
128 !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
130 Status = NDIS_STATUS_FAILURE;
134 // Check Free priority queue
135 // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing.
138 if (pAd->MACVersion == 0x28600100)
140 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
144 FreeNum = GET_MGMTRING_FREENO(pAd);
149 // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870
150 NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE));
151 Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE), pData, Length);
152 if (Status != NDIS_STATUS_SUCCESS)
154 DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
158 //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
159 //pAd->CommonCfg.MlmeRate = RATE_2;
162 Status = MlmeHardTransmit(pAd, QueIdx, pPacket);
163 if (Status != NDIS_STATUS_SUCCESS)
164 RTMPFreeNdisPacket(pAd, pPacket);
168 pAd->RalinkCounters.MgmtRingFullCount++;
169 DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n",
170 QueIdx, pAd->RalinkCounters.MgmtRingFullCount));
176 if ((pAd->MACVersion == 0x28600100) && (!IrqState))
177 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
183 NDIS_STATUS MiniportMMRequestUnlock(
184 IN PRTMP_ADAPTER pAd,
189 PNDIS_PACKET pPacket;
190 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
197 ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
201 // Reset is in progress, stop immediately
202 if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
203 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)||
204 !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
206 Status = NDIS_STATUS_FAILURE;
210 // Check Free priority queue
211 // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing.
213 if (pAd->MACVersion == 0x28600100)
215 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
216 SW_TX_IDX = pAd->TxRing[QueIdx].TxCpuIdx;
217 pTxD = (PTXD_STRUC) pAd->TxRing[QueIdx].Cell[SW_TX_IDX].AllocVa;
221 FreeNum = GET_MGMTRING_FREENO(pAd);
222 SW_TX_IDX = pAd->MgmtRing.TxCpuIdx;
223 pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[SW_TX_IDX].AllocVa;
227 NdisZeroMemory(&TXWI, TXWI_SIZE);
228 Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&TXWI, TXWI_SIZE, pData, Length);
229 if (Status != NDIS_STATUS_SUCCESS)
231 DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
235 Status = MlmeHardTransmit(pAd, QueIdx, pPacket);
236 if (Status != NDIS_STATUS_SUCCESS)
237 RTMPFreeNdisPacket(pAd, pPacket);
241 pAd->RalinkCounters.MgmtRingFullCount++;
242 DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing\n", QueIdx));
253 ========================================================================
256 Copy frame from waiting queue into relative ring buffer and set
257 appropriate ASIC register to kick hardware transmit function
260 pAd Pointer to our adapter
261 pBuffer Pointer to memory of outgoing frame
262 Length Size of outgoing management frame
270 IRQL = DISPATCH_LEVEL
274 ========================================================================
276 NDIS_STATUS MlmeHardTransmit(
277 IN PRTMP_ADAPTER pAd,
279 IN PNDIS_PACKET pPacket)
281 if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
283 return NDIS_STATUS_FAILURE;
286 if ( pAd->MACVersion == 0x28600100 )
287 return MlmeHardTransmitTxRing(pAd,QueIdx,pPacket);
289 return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
294 NDIS_STATUS MlmeHardTransmitTxRing(
295 IN PRTMP_ADAPTER pAd,
297 IN PNDIS_PACKET pPacket)
299 PACKET_INFO PacketInfo;
307 PHEADER_802_11 pHeader_802_11;
308 BOOLEAN bAckRequired, bInsertTimestamp;
311 ULONG SwIdx = pAd->TxRing[QueIdx].TxCpuIdx;
312 PTXWI_STRUC pFirstTxWI;
314 MAC_TABLE_ENTRY *pMacEntry = NULL;
317 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
319 if (pSrcBufVA == NULL)
321 // The buffer shouldn't be NULL
322 return NDIS_STATUS_FAILURE;
325 // Make sure MGMT ring resource won't be used by other threads
326 //NdisAcquireSpinLock(&pAd->TxRingLock);
328 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
332 //NdisReleaseSpinLock(&pAd->TxRingLock);
333 return NDIS_STATUS_FAILURE;
336 SwIdx = pAd->TxRing[QueIdx].TxCpuIdx;
338 #ifndef RT_BIG_ENDIAN
339 pTxD = (PTXD_STRUC) pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa;
341 pDestTxD = (PTXD_STRUC)pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa;
344 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
347 if (pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket)
349 printk("MlmeHardTransmit Error\n");
350 return NDIS_STATUS_FAILURE;
354 #ifdef CONFIG_STA_SUPPORT
355 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
357 // outgoing frame always wakeup PHY to prevent frame lost
358 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
359 AsicForceWakeup(pAd, FROM_TX);
361 #endif // CONFIG_STA_SUPPORT //
362 pFirstTxWI =(PTXWI_STRUC)pSrcBufVA;
364 pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXWI_SIZE);
365 if (pHeader_802_11->Addr1[0] & 0x01)
367 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
371 MlmeRate = pAd->CommonCfg.MlmeRate;
374 if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
375 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
377 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
380 // Verify Mlme rate for a / g bands.
381 if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
385 // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
386 // Snice it's been set to 0 while on MgtMacHeaderInit
387 // By the way this will cause frame to be send on PWR_SAVE failed.
390 // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
391 #ifdef CONFIG_STA_SUPPORT
392 // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
393 if (pHeader_802_11->FC.Type != BTYPE_DATA)
395 if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_REQ) || !(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
397 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
401 pHeader_802_11->FC.PwrMgmt = pAd->CommonCfg.bAPSDForcePowerSave;
404 #endif // CONFIG_STA_SUPPORT //
406 bInsertTimestamp = FALSE;
407 if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
409 bAckRequired = FALSE;
411 else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
413 if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
415 bAckRequired = FALSE;
416 pHeader_802_11->Duration = 0;
421 pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
422 if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
424 bInsertTimestamp = TRUE;
428 pHeader_802_11->Sequence = pAd->Sequence++;
429 if (pAd->Sequence > 0xfff)
431 // Before radar detection done, mgmt frame can not be sent but probe req
432 // Because we need to use probe req to trigger driver to send probe req in passive scan
433 if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
434 && (pAd->CommonCfg.bIEEE80211H == 1)
435 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
437 DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
438 return (NDIS_STATUS_FAILURE);
442 RTMPFrameEndianChange(pAd, (PUCHAR)pHeader_802_11, DIR_WRITE, FALSE);
445 // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
446 // should always has only one ohysical buffer, and the whole frame size equals
447 // to the first scatter buffer size
450 // Initialize TX Descriptor
451 // For inter-frame gap, the number is for this frame and next frame
452 // For MLME rate, we will fix as 2Mb to match other vendor's implement
454 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
455 // Only beacon use Nseq=TRUE. So here we use Nseq=FALSE.
456 if (pMacEntry == NULL)
458 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
459 0, RESERVED_WCID, (SrcBufLen - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
463 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
464 bInsertTimestamp, FALSE, bAckRequired, FALSE,
465 0, pMacEntry->Aid, (SrcBufLen - TXWI_SIZE),
466 pMacEntry->MaxHTPhyMode.field.MCS, 0,
467 (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
468 IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
471 pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket = pPacket;
472 pAd->TxRing[QueIdx].Cell[SwIdx].pNextNdisPacket = NULL;
474 RTMPWIEndianChange((PUCHAR)pFirstTxWI, TYPE_TXWI);
476 SrcBufPA = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE);
479 RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_EDCA);
482 pTxD->SDLen0 = SrcBufLen;
484 pTxD->SDPtr0 = SrcBufPA;
488 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
489 WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
492 pAd->RalinkCounters.KickTxCount++;
493 pAd->RalinkCounters.OneSecTxDoneCount++;
495 // Increase TX_CTX_IDX, but write to register later.
496 INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE);
498 RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx*0x10, pAd->TxRing[QueIdx].TxCpuIdx);
500 return NDIS_STATUS_SUCCESS;
504 NDIS_STATUS MlmeHardTransmitMgmtRing(
505 IN PRTMP_ADAPTER pAd,
507 IN PNDIS_PACKET pPacket)
509 PACKET_INFO PacketInfo;
512 PHEADER_802_11 pHeader_802_11;
513 BOOLEAN bAckRequired, bInsertTimestamp;
515 PTXWI_STRUC pFirstTxWI;
516 MAC_TABLE_ENTRY *pMacEntry = NULL;
518 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
519 RTMP_SEM_LOCK(&pAd->MgmtRingLock);
522 if (pSrcBufVA == NULL)
524 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
525 return NDIS_STATUS_FAILURE;
528 #ifdef CONFIG_STA_SUPPORT
529 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
531 // outgoing frame always wakeup PHY to prevent frame lost
532 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
533 AsicForceWakeup(pAd, FROM_TX);
535 #endif // CONFIG_STA_SUPPORT //
537 pFirstTxWI = (PTXWI_STRUC)(pSrcBufVA + TXINFO_SIZE);
538 pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); //TXWI_SIZE);
540 if (pHeader_802_11->Addr1[0] & 0x01)
542 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
546 MlmeRate = pAd->CommonCfg.MlmeRate;
549 // Verify Mlme rate for a / g bands.
550 if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
553 if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
554 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
556 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
559 #ifdef CONFIG_STA_SUPPORT
560 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
562 // Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode.
563 if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED
564 #ifdef DOT11_N_SUPPORT
565 || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED
566 #endif // DOT11_N_SUPPORT //
569 if (pAd->LatchRfRegs.Channel > 14)
570 pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
572 pAd->CommonCfg.MlmeTransmit.field.MODE = 0;
575 #endif // CONFIG_STA_SUPPORT //
578 // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
579 // Snice it's been set to 0 while on MgtMacHeaderInit
580 // By the way this will cause frame to be send on PWR_SAVE failed.
582 // pHeader_802_11->FC.PwrMgmt = 0; // (pAd->StaCfg.Psm == PWR_SAVE);
584 // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
585 #ifdef CONFIG_STA_SUPPORT
586 // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
587 if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL))
589 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
590 (pHeader_802_11->FC.SubType == SUBTYPE_ACTION))
591 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
593 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
595 #endif // CONFIG_STA_SUPPORT //
597 bInsertTimestamp = FALSE;
598 if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
600 #ifdef CONFIG_STA_SUPPORT
601 //Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue.
602 if ((pAd->OpMode == OPMODE_STA) && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL))
604 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
606 #endif // CONFIG_STA_SUPPORT //
607 bAckRequired = FALSE;
609 else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
611 if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
613 bAckRequired = FALSE;
614 pHeader_802_11->Duration = 0;
619 pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
620 if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
622 bInsertTimestamp = TRUE;
627 pHeader_802_11->Sequence = pAd->Sequence++;
628 if (pAd->Sequence >0xfff)
631 // Before radar detection done, mgmt frame can not be sent but probe req
632 // Because we need to use probe req to trigger driver to send probe req in passive scan
633 if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
634 && (pAd->CommonCfg.bIEEE80211H == 1)
635 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
637 DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
638 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
639 return (NDIS_STATUS_FAILURE);
643 RTMPFrameEndianChange(pAd, (PUCHAR)pHeader_802_11, DIR_WRITE, FALSE);
647 // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
648 // should always has only one ohysical buffer, and the whole frame size equals
649 // to the first scatter buffer size
652 // Initialize TX Descriptor
653 // For inter-frame gap, the number is for this frame and next frame
654 // For MLME rate, we will fix as 2Mb to match other vendor's implement
656 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
657 if (pMacEntry == NULL)
659 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
660 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
664 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
665 bInsertTimestamp, FALSE, bAckRequired, FALSE,
666 0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE),
667 pMacEntry->MaxHTPhyMode.field.MCS, 0,
668 (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
669 IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
673 RTMPWIEndianChange((PUCHAR)pFirstTxWI, TYPE_TXWI);
676 // Now do hardware-depened kick out.
677 HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen);
679 // Make sure to release MGMT ring resource
680 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
681 return NDIS_STATUS_SUCCESS;
685 /********************************************************************************
687 New DeQueue Procedures.
689 ********************************************************************************/
691 #define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \
693 if (bIntContext == FALSE) \
694 RTMP_IRQ_LOCK((lock), IrqFlags); \
697 #define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \
699 if (bIntContext == FALSE) \
700 RTMP_IRQ_UNLOCK((lock), IrqFlags); \
704 ========================================================================
705 Tx Path design algorithm:
706 Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal),
707 Specific Packet Type. Following show the classification rule and policy for each kinds of packets.
708 Classification Rule=>
709 Multicast: (*addr1 & 0x01) == 0x01
710 Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc.
711 11N Rate : If peer support HT
712 (1).AMPDU -- If TXBA is negotiated.
713 (2).AMSDU -- If AMSDU is capable for both peer and ourself.
714 *). AMSDU can embedded in a AMPDU, but now we didn't support it.
715 (3).Normal -- Other packets which send as 11n rate.
717 B/G Rate : If peer is b/g only.
718 (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6
719 (2).Normal -- Other packets which send as b/g rate.
721 The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
723 Classified Packet Handle Rule=>
725 No ACK, //pTxBlk->bAckRequired = FALSE;
726 No WMM, //pTxBlk->bWMM = FALSE;
727 No piggyback, //pTxBlk->bPiggyBack = FALSE;
728 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
729 Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use
730 the same policy to handle it.
731 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
734 No piggyback, //pTxBlk->bPiggyBack = FALSE;
746 ========================================================================
748 static UCHAR TxPktClassification(
749 IN RTMP_ADAPTER *pAd,
750 IN PNDIS_PACKET pPacket)
752 UCHAR TxFrameType = TX_UNKOWN_FRAME;
754 MAC_TABLE_ENTRY *pMacEntry = NULL;
755 #ifdef DOT11_N_SUPPORT
756 BOOLEAN bHTRate = FALSE;
757 #endif // DOT11_N_SUPPORT //
759 Wcid = RTMP_GET_PACKET_WCID(pPacket);
760 if (Wcid == MCAST_WCID)
761 { // Handle for RA is Broadcast/Multicast Address.
762 return TX_MCAST_FRAME;
765 // Handle for unicast packets
766 pMacEntry = &pAd->MacTab.Content[Wcid];
767 if (RTMP_GET_PACKET_LOWRATE(pPacket))
768 { // It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame
769 TxFrameType = TX_LEGACY_FRAME;
771 #ifdef DOT11_N_SUPPORT
772 else if (IS_HT_RATE(pMacEntry))
773 { // it's a 11n capable packet
775 // Depends on HTPhyMode to check if the peer support the HTRate transmission.
776 // Currently didn't support A-MSDU embedded in A-MPDU
778 if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE))
779 TxFrameType = TX_LEGACY_FRAME;
780 #ifdef UAPSD_AP_SUPPORT
781 else if (RTMP_GET_PACKET_EOSP(pPacket))
782 TxFrameType = TX_LEGACY_FRAME;
783 #endif // UAPSD_AP_SUPPORT //
784 else if((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0)
785 return TX_AMPDU_FRAME;
786 else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED))
787 return TX_AMSDU_FRAME;
789 TxFrameType = TX_LEGACY_FRAME;
791 #endif // DOT11_N_SUPPORT //
793 { // it's a legacy b/g packet.
794 if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) &&
795 (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) &&
796 (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
797 { // if peer support Ralink Aggregation, we use it.
798 TxFrameType = TX_RALINK_FRAME;
802 TxFrameType = TX_LEGACY_FRAME;
806 // Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU.
807 if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) && (TxFrameType == TX_LEGACY_FRAME))
808 TxFrameType = TX_FRAG_FRAME;
814 BOOLEAN RTMP_FillTxBlkInfo(
815 IN RTMP_ADAPTER *pAd,
818 PACKET_INFO PacketInfo;
819 PNDIS_PACKET pPacket;
820 PMAC_TABLE_ENTRY pMacEntry = NULL;
822 pPacket = pTxBlk->pPacket;
823 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
825 pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket);
826 pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket);
827 pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket);
828 pTxBlk->FrameGap = IFS_HTTXOP; // ASIC determine Frame Gap
830 if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket))
831 TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame);
833 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame);
835 // Default to clear this flag
836 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS);
839 if (pTxBlk->Wcid == MCAST_WCID)
841 pTxBlk->pMacEntry = NULL;
843 #ifdef MCAST_RATE_SPECIFIC
844 PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket);
845 if (((*pDA & 0x01) == 0x01) && (*pDA != 0xff))
846 pTxBlk->pTransmit = &pAd->CommonCfg.MCastPhyMode;
848 #endif // MCAST_RATE_SPECIFIC //
849 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
852 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); // AckRequired = FALSE, when broadcast packet in Adhoc mode.
853 //TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate);
854 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag);
855 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
856 if (RTMP_GET_PACKET_MOREDATA(pPacket))
858 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
864 pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
865 pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode;
867 pMacEntry = pTxBlk->pMacEntry;
870 // For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK.
871 if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK)
872 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
874 TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired);
878 #ifdef CONFIG_STA_SUPPORT
879 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
882 // If support WMM, enable it.
883 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
884 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM);
886 #endif // CONFIG_STA_SUPPORT //
889 if (pTxBlk->TxFrameType == TX_LEGACY_FRAME)
891 if ( (RTMP_GET_PACKET_LOWRATE(pPacket)) ||
892 ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1)))
893 { // Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate.
894 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
895 #ifdef DOT11_N_SUPPORT
896 // Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it???
897 if (IS_HT_STA(pTxBlk->pMacEntry) &&
898 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) &&
899 ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)))
901 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
902 TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS);
904 #endif // DOT11_N_SUPPORT //
907 #ifdef DOT11_N_SUPPORT
908 if ( (IS_HT_RATE(pMacEntry) == FALSE) &&
909 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE)))
910 { // Currently piggy-back only support when peer is operate in b/g mode.
911 TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack);
913 #endif // DOT11_N_SUPPORT //
915 if (RTMP_GET_PACKET_MOREDATA(pPacket))
917 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
919 #ifdef UAPSD_AP_SUPPORT
920 if (RTMP_GET_PACKET_EOSP(pPacket))
922 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP);
924 #endif // UAPSD_AP_SUPPORT //
926 else if (pTxBlk->TxFrameType == TX_FRAG_FRAME)
928 TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag);
931 pMacEntry->DebugTxCount++;
938 BOOLEAN CanDoAggregateTransmit(
939 IN RTMP_ADAPTER *pAd,
940 IN NDIS_PACKET *pPacket,
944 //printk("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType);
946 if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
949 if (RTMP_GET_PACKET_DHCP(pPacket) ||
950 RTMP_GET_PACKET_EAPOL(pPacket) ||
951 RTMP_GET_PACKET_WAI(pPacket))
954 if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) &&
955 ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100)))
956 { // For AMSDU, allow the packets with total length < max-amsdu size
960 if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) &&
961 (pTxBlk->TxPacketList.Number == 2))
962 { // For RALINK-Aggregation, allow two frames in one batch.
966 #ifdef CONFIG_STA_SUPPORT
967 if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP
970 #endif // CONFIG_STA_SUPPORT //
977 ========================================================================
980 To do the enqueue operation and extract the first item of waiting
981 list. If a number of available shared memory segments could meet
982 the request of extracted item, the extracted item will be fragmented
983 into shared memory segments.
986 pAd Pointer to our adapter
987 pQueue Pointer to Waiting Queue
992 IRQL = DISPATCH_LEVEL
996 ========================================================================
998 VOID RTMPDeQueuePacket(
999 IN PRTMP_ADAPTER pAd,
1000 IN BOOLEAN bIntContext,
1001 IN UCHAR QIdx, /* BulkOutPipeId */
1002 IN UCHAR Max_Tx_Packets)
1004 PQUEUE_ENTRY pEntry = NULL;
1005 PNDIS_PACKET pPacket;
1006 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
1008 PQUEUE_HEADER pQueue;
1009 ULONG FreeNumber[NUM_OF_TX_RING];
1010 UCHAR QueIdx, sQIdx, eQIdx;
1011 unsigned long IrqFlags = 0;
1012 BOOLEAN hasTxDesc = FALSE;
1018 RtmpDiagStruct *pDiagStruct = &pAd->DiagStruct;
1022 if (QIdx == NUM_OF_TX_RING)
1025 eQIdx = 3; // 4 ACs, start from 0.
1029 sQIdx = eQIdx = QIdx;
1032 for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++)
1036 RT28XX_START_DEQUEUE(pAd, QueIdx, IrqFlags);
1039 firstRound = ((QueIdx == 0) ? TRUE : FALSE);
1040 #endif // DBG_DIAGNOSE //
1044 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |
1045 fRTMP_ADAPTER_RADIO_OFF |
1046 fRTMP_ADAPTER_RESET_IN_PROGRESS |
1047 fRTMP_ADAPTER_HALT_IN_PROGRESS |
1048 fRTMP_ADAPTER_NIC_NOT_EXIST))))
1050 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
1054 if (Count >= Max_Tx_Packets)
1057 DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1058 if (&pAd->TxSwQueue[QueIdx] == NULL)
1061 if (firstRound == TRUE)
1062 pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][0]++;
1063 #endif // DBG_DIAGNOSE //
1064 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1068 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
1071 if (firstRound == TRUE)
1073 UCHAR txDescNumLevel, txSwQNumLevel;
1075 txDescNumLevel = (TX_RING_SIZE - FreeNumber[QueIdx]); // Number of occupied hw desc.
1076 txDescNumLevel = ((txDescNumLevel <=15) ? txDescNumLevel : 15);
1077 pDiagStruct->TxDescCnt[pDiagStruct->ArrayCurIdx][txDescNumLevel]++;
1079 txSwQNumLevel = ((pAd->TxSwQueue[QueIdx].Number <=7) ? pAd->TxSwQueue[QueIdx].Number : 8);
1080 pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][txSwQNumLevel]++;
1084 #endif // DBG_DIAGNOSE //
1086 if (FreeNumber[QueIdx] <= 5)
1088 // free Tx(QueIdx) resources
1089 RTMPFreeTXDUponTxDmaDone(pAd, QueIdx);
1090 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
1093 // probe the Queue Head
1094 pQueue = &pAd->TxSwQueue[QueIdx];
1095 if ((pEntry = pQueue->Head) == NULL)
1097 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1102 NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK));
1103 pTxBlk->QueIdx = QueIdx;
1105 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
1107 // Early check to make sure we have enoguh Tx Resource.
1108 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
1111 pAd->PrivateInfo.TxRingFullCnt++;
1113 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1118 pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
1119 pEntry = RemoveHeadQueue(pQueue);
1120 pTxBlk->TotalFrameNum++;
1121 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
1122 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
1123 pTxBlk->pPacket = pPacket;
1124 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
1126 if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME)
1128 // Enhance SW Aggregation Mechanism
1129 if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType))
1131 InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
1132 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1137 if((pEntry = pQueue->Head) == NULL)
1140 // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation.
1141 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
1142 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
1143 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
1144 if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE))
1147 //Remove the packet from the TxSwQueue and insert into pTxBlk
1148 pEntry = RemoveHeadQueue(pQueue);
1150 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
1151 pTxBlk->TotalFrameNum++;
1152 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
1153 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
1154 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
1157 if (pTxBlk->TxPacketList.Number == 1)
1158 pTxBlk->TxFrameType = TX_LEGACY_FRAME;
1162 Count += pTxBlk->TxPacketList.Number;
1164 // Do HardTransmit now.
1165 #ifdef CONFIG_STA_SUPPORT
1166 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1167 Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
1168 #endif // CONFIG_STA_SUPPORT //
1170 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1171 // static rate also need NICUpdateFifoStaCounters() function.
1172 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
1173 NICUpdateFifoStaCounters(pAd);
1176 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
1180 if ((pAd->blockQueueTab[QueIdx].SwTxQueueBlockFlag == TRUE)
1181 && (pAd->TxSwQueue[QueIdx].Number < 1))
1183 releaseNetIf(&pAd->blockQueueTab[QueIdx]);
1185 #endif // BLOCK_NET_IF //
1193 ========================================================================
1195 Routine Description:
1196 Calculates the duration which is required to transmit out frames
1197 with given size and specified rate.
1200 pAd Pointer to our adapter
1202 Size Frame size in units of byte
1205 Duration number in units of usec
1207 IRQL = PASSIVE_LEVEL
1208 IRQL = DISPATCH_LEVEL
1212 ========================================================================
1214 USHORT RTMPCalcDuration(
1215 IN PRTMP_ADAPTER pAd,
1221 if (Rate < RATE_FIRST_OFDM_RATE) // CCK
1223 if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED))
1224 Duration = 96; // 72+24 preamble+plcp
1226 Duration = 192; // 144+48 preamble+plcp
1228 Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]);
1229 if ((Size << 4) % RateIdTo500Kbps[Rate])
1232 else if (Rate <= RATE_LAST_OFDM_RATE)// OFDM rates
1234 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
1235 Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
1236 if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
1241 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
1244 return (USHORT)Duration;
1249 ========================================================================
1251 Routine Description:
1252 Calculates the duration which is required to transmit out frames
1253 with given size and specified rate.
1256 pTxWI Pointer to head of each MPDU to HW.
1257 Ack Setting for Ack requirement bit
1258 Fragment Setting for Fragment bit
1259 RetryMode Setting for retry mode
1260 Ifs Setting for IFS gap
1261 Rate Setting for transmit rate
1262 Service Setting for service
1264 TxPreamble Short or Long preamble when using CCK rates
1265 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1270 IRQL = PASSIVE_LEVEL
1271 IRQL = DISPATCH_LEVEL
1273 See also : BASmartHardTransmit() !!!
1275 ========================================================================
1278 IN PRTMP_ADAPTER pAd,
1279 IN PTXWI_STRUC pOutTxWI,
1282 IN BOOLEAN InsTimestamp,
1285 IN BOOLEAN NSeq, // HW new a sequence.
1294 IN HTTRANSMIT_SETTING *pTransmit)
1296 PMAC_TABLE_ENTRY pMac = NULL;
1300 if (WCID < MAX_LEN_OF_MAC_TABLE)
1301 pMac = &pAd->MacTab.Content[WCID];
1304 // Always use Long preamble before verifiation short preamble functionality works well.
1305 // Todo: remove the following line if short preamble functionality works
1307 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1308 NdisZeroMemory(&TxWI, TXWI_SIZE);
1313 pTxWI->CFACK = CFACK;
1314 pTxWI->TS= InsTimestamp;
1315 pTxWI->AMPDU = AMPDU;
1317 pTxWI->txop= Txopmode;
1320 // John tune the performace with Intel Client in 20 MHz performance
1321 #ifdef DOT11_N_SUPPORT
1322 BASize = pAd->CommonCfg.TxBASize;
1326 pTxWI->BAWinSize = BASize;
1327 pTxWI->ShortGI = pTransmit->field.ShortGI;
1328 pTxWI->STBC = pTransmit->field.STBC;
1329 #endif // DOT11_N_SUPPORT //
1331 pTxWI->WirelessCliID = WCID;
1332 pTxWI->MPDUtotalByteCount = Length;
1333 pTxWI->PacketId = PID;
1335 // If CCK or OFDM, BW must be 20
1336 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1337 #ifdef DOT11N_DRAFT3
1339 pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1340 #endif // DOT11N_DRAFT3 //
1342 pTxWI->MCS = pTransmit->field.MCS;
1343 pTxWI->PHYMODE = pTransmit->field.MODE;
1344 pTxWI->CFACK = CfAck;
1346 #ifdef DOT11_N_SUPPORT
1349 if (pAd->CommonCfg.bMIMOPSEnable)
1351 if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1353 // Dynamic MIMO Power Save Mode
1356 else if (pMac->MmpsMode == MMPS_STATIC)
1358 // Static MIMO Power Save Mode
1359 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1366 //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;
1367 if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled))
1369 pTxWI->MpduDensity = 7;
1373 pTxWI->MpduDensity = pMac->MpduDensity;
1376 #endif // DOT11_N_SUPPORT //
1378 pTxWI->PacketId = pTxWI->MCS;
1379 NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC));
1383 VOID RTMPWriteTxWI_Data(
1384 IN PRTMP_ADAPTER pAd,
1385 IN OUT PTXWI_STRUC pTxWI,
1388 HTTRANSMIT_SETTING *pTransmit;
1389 PMAC_TABLE_ENTRY pMacEntry;
1390 #ifdef DOT11_N_SUPPORT
1392 #endif // DOT11_N_SUPPORT //
1397 pTransmit = pTxBlk->pTransmit;
1398 pMacEntry = pTxBlk->pMacEntry;
1402 // Always use Long preamble before verifiation short preamble functionality works well.
1403 // Todo: remove the following line if short preamble functionality works
1405 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1406 NdisZeroMemory(pTxWI, TXWI_SIZE);
1408 pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1409 pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1410 pTxWI->txop = pTxBlk->FrameGap;
1412 #ifdef CONFIG_STA_SUPPORT
1413 #ifdef QOS_DLS_SUPPORT
1415 (pAd->StaCfg.BssType == BSS_INFRA) &&
1416 (pMacEntry->ValidAsDls == TRUE))
1417 pTxWI->WirelessCliID = BSSID_WCID;
1419 #endif // QOS_DLS_SUPPORT //
1420 #endif // CONFIG_STA_SUPPORT //
1421 pTxWI->WirelessCliID = pTxBlk->Wcid;
1423 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1424 pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
1426 // If CCK or OFDM, BW must be 20
1427 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1428 #ifdef DOT11_N_SUPPORT
1429 #ifdef DOT11N_DRAFT3
1431 pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1432 #endif // DOT11N_DRAFT3 //
1433 pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
1435 // John tune the performace with Intel Client in 20 MHz performance
1436 BASize = pAd->CommonCfg.TxBASize;
1437 if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry))
1439 UCHAR RABAOriIdx = 0; //The RA's BA Originator table index.
1441 RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
1442 BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1445 pTxWI->TxBF = pTransmit->field.TxBF;
1446 pTxWI->BAWinSize = BASize;
1447 pTxWI->ShortGI = pTransmit->field.ShortGI;
1448 pTxWI->STBC = pTransmit->field.STBC;
1449 #endif // DOT11_N_SUPPORT //
1451 pTxWI->MCS = pTransmit->field.MCS;
1452 pTxWI->PHYMODE = pTransmit->field.MODE;
1454 #ifdef DOT11_N_SUPPORT
1457 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1459 // Dynamic MIMO Power Save Mode
1462 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1464 // Static MIMO Power Save Mode
1465 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1472 if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled))
1474 pTxWI->MpduDensity = 7;
1478 pTxWI->MpduDensity = pMacEntry->MpduDensity;
1481 #endif // DOT11_N_SUPPORT //
1484 if (pTxBlk->QueIdx== 0)
1486 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1487 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1489 #endif // DBG_DIAGNOSE //
1491 // for rate adapation
1492 pTxWI->PacketId = pTxWI->MCS;
1496 VOID RTMPWriteTxWI_Cache(
1497 IN PRTMP_ADAPTER pAd,
1498 IN OUT PTXWI_STRUC pTxWI,
1501 PHTTRANSMIT_SETTING pTransmit;
1502 PMAC_TABLE_ENTRY pMacEntry;
1507 pMacEntry = pTxBlk->pMacEntry;
1508 pTransmit = pTxBlk->pTransmit;
1510 if (pMacEntry->bAutoTxRateSwitch)
1512 pTxWI->txop = IFS_HTTXOP;
1514 // If CCK or OFDM, BW must be 20
1515 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1516 pTxWI->ShortGI = pTransmit->field.ShortGI;
1517 pTxWI->STBC = pTransmit->field.STBC;
1519 pTxWI->MCS = pTransmit->field.MCS;
1520 pTxWI->PHYMODE = pTransmit->field.MODE;
1522 // set PID for TxRateSwitching
1523 pTxWI->PacketId = pTransmit->field.MCS;
1526 #ifdef DOT11_N_SUPPORT
1527 pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE);
1530 #ifdef DOT11N_DRAFT3
1532 pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1533 #endif // DOT11N_DRAFT3 //
1535 if (pAd->CommonCfg.bMIMOPSEnable)
1537 // MIMO Power Save Mode
1538 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1540 // Dynamic MIMO Power Save Mode
1543 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1545 // Static MIMO Power Save Mode
1546 if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7))
1553 #endif // DOT11_N_SUPPORT //
1556 if (pTxBlk->QueIdx== 0)
1558 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1559 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1561 #endif // DBG_DIAGNOSE //
1563 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1569 ========================================================================
1571 Routine Description:
1572 Calculates the duration which is required to transmit out frames
1573 with given size and specified rate.
1576 pTxD Pointer to transmit descriptor
1577 Ack Setting for Ack requirement bit
1578 Fragment Setting for Fragment bit
1579 RetryMode Setting for retry mode
1580 Ifs Setting for IFS gap
1581 Rate Setting for transmit rate
1582 Service Setting for service
1584 TxPreamble Short or Long preamble when using CCK rates
1585 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1590 IRQL = PASSIVE_LEVEL
1591 IRQL = DISPATCH_LEVEL
1593 ========================================================================
1595 VOID RTMPWriteTxDescriptor(
1596 IN PRTMP_ADAPTER pAd,
1602 // Always use Long preamble before verifiation short preamble functionality works well.
1603 // Todo: remove the following line if short preamble functionality works
1605 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1607 pTxD->WIV = (bWIV) ? 1: 0;
1608 pTxD->QSEL= (QueueSEL);
1609 if (pAd->bGenOneHCCA == TRUE)
1610 pTxD->QSEL= FIFO_HCCA;
1615 // should be called only when -
1616 // 1. MEADIA_CONNECTED
1617 // 2. AGGREGATION_IN_USED
1618 // 3. Fragmentation not in used
1619 // 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible
1620 BOOLEAN TxFrameIsAggregatible(
1621 IN PRTMP_ADAPTER pAd,
1622 IN PUCHAR pPrevAddr1,
1626 // can't aggregate EAPOL (802.1x) frame
1627 if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1630 // can't aggregate multicast/broadcast frame
1631 if (p8023hdr[0] & 0x01)
1634 if (INFRA_ON(pAd)) // must be unicast to AP
1636 else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA
1644 ========================================================================
1646 Routine Description:
1647 Check the MSDU Aggregation policy
1648 1.HT aggregation is A-MSDU
1649 2.legaacy rate aggregation is software aggregation by Ralink.
1657 ========================================================================
1659 BOOLEAN PeerIsAggreOn(
1660 IN PRTMP_ADAPTER pAd,
1662 IN PMAC_TABLE_ENTRY pMacEntry)
1664 ULONG AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
1666 if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags))
1668 #ifdef DOT11_N_SUPPORT
1669 if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX)
1673 #endif // DOT11_N_SUPPORT //
1675 #ifdef AGGREGATION_SUPPORT
1676 if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
1677 { // legacy Ralink Aggregation support
1680 #endif // AGGREGATION_SUPPORT //
1689 ========================================================================
1691 Routine Description:
1692 Check and fine the packet waiting in SW queue with highest priority
1695 pAd Pointer to our adapter
1698 pQueue Pointer to Waiting Queue
1700 IRQL = DISPATCH_LEVEL
1704 ========================================================================
1706 PQUEUE_HEADER RTMPCheckTxSwQueue(
1707 IN PRTMP_ADAPTER pAd,
1713 Number = pAd->TxSwQueue[QID_AC_BK].Number
1714 + pAd->TxSwQueue[QID_AC_BE].Number
1715 + pAd->TxSwQueue[QID_AC_VI].Number
1716 + pAd->TxSwQueue[QID_AC_VO].Number
1717 + pAd->TxSwQueue[QID_HCCA].Number;
1719 if (pAd->TxSwQueue[QID_AC_VO].Head != NULL)
1721 *pQueIdx = QID_AC_VO;
1722 return (&pAd->TxSwQueue[QID_AC_VO]);
1724 else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL)
1726 *pQueIdx = QID_AC_VI;
1727 return (&pAd->TxSwQueue[QID_AC_VI]);
1729 else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL)
1731 *pQueIdx = QID_AC_BE;
1732 return (&pAd->TxSwQueue[QID_AC_BE]);
1734 else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL)
1736 *pQueIdx = QID_AC_BK;
1737 return (&pAd->TxSwQueue[QID_AC_BK]);
1739 else if (pAd->TxSwQueue[QID_HCCA].Head != NULL)
1741 *pQueIdx = QID_HCCA;
1742 return (&pAd->TxSwQueue[QID_HCCA]);
1745 // No packet pending in Tx Sw queue
1746 *pQueIdx = QID_AC_BK;
1752 BOOLEAN RTMPFreeTXDUponTxDmaDone(
1753 IN PRTMP_ADAPTER pAd,
1756 PRTMP_TX_RING pTxRing;
1758 #ifdef RT_BIG_ENDIAN
1759 PTXD_STRUC pDestTxD;
1761 PNDIS_PACKET pPacket;
1763 TXD_STRUC TxD, *pOriTxD;
1765 BOOLEAN bReschedule = FALSE;
1768 ASSERT(QueIdx < NUM_OF_TX_RING);
1769 pTxRing = &pAd->TxRing[QueIdx];
1771 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF, &pTxRing->TxDmaIdx);
1772 while (pTxRing->TxSwFreeIdx != pTxRing->TxDmaIdx)
1775 #ifdef RALINK_28xx_QA
1776 PHEADER_802_11 pHeader80211;
1778 if ((ATE_ON(pAd)) && (pAd->ate.bQATxStart == TRUE))
1780 if (pAd->ate.QID == QueIdx)
1782 pAd->ate.TxDoneCount++;
1783 //pAd->ate.Repeat++;
1784 pAd->RalinkCounters.KickTxCount++;
1786 /* always use QID_AC_BE and FIFO_EDCA */
1787 ASSERT(pAd->ate.QID == 0);
1791 #ifndef RT_BIG_ENDIAN
1792 pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
1794 NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC));
1797 pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
1798 pOriTxD = pDestTxD ;
1801 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
1805 pHeader80211 = pTxRing->Cell[pTxRing->TxSwFreeIdx].DmaBuf.AllocVa + sizeof(TXWI_STRUC);
1806 #ifdef RT_BIG_ENDIAN
1807 RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_READ, FALSE);
1809 pHeader80211->Sequence = ++pAd->ate.seq;
1810 #ifdef RT_BIG_ENDIAN
1811 RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_WRITE, FALSE);
1814 if ((pAd->ate.bQATxStart == TRUE) && (pAd->ate.Mode & ATE_TXFRAME) && (pAd->ate.TxDoneCount < pAd->ate.TxCount))
1816 pAd->RalinkCounters.TransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0);
1817 pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++;
1818 INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE);
1819 /* get tx_tdx_idx again */
1820 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &pTxRing->TxDmaIdx);
1823 else if ((pAd->ate.TxStatus == 1)/* or (pAd->ate.bQATxStart == TRUE) ??? */ && (pAd->ate.TxDoneCount == pAd->ate.TxCount))//<========================PETER
1825 DBGPRINT(RT_DEBUG_TRACE,("all Tx is done\n"));
1826 // Tx status enters idle mode.
1827 pAd->ate.TxStatus = 0;
1829 else if (!(pAd->ate.Mode & ATE_TXFRAME))
1831 /* not complete sending yet, but someone press the Stop TX botton. */
1832 DBGPRINT(RT_DEBUG_ERROR,("not complete sending yet, but someone pressed the Stop TX bottom\n"));
1833 DBGPRINT(RT_DEBUG_ERROR,("pAd->ate.Mode = 0x%02x\n", pAd->ate.Mode));
1837 DBGPRINT(RT_DEBUG_OFF,("pTxRing->TxSwFreeIdx = %d\n", pTxRing->TxSwFreeIdx));
1839 #ifndef RT_BIG_ENDIAN
1840 NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC));
1842 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
1844 #endif // RT_BIG_ENDIAN //
1846 INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE);
1850 #endif // RALINK_28xx_QA //
1851 #endif // RALINK_ATE //
1853 // static rate also need NICUpdateFifoStaCounters() function.
1854 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
1855 NICUpdateFifoStaCounters(pAd);
1857 /* Note : If (pAd->ate.bQATxStart == TRUE), we will never reach here. */
1859 #ifndef RT_BIG_ENDIAN
1860 pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
1862 NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC));
1865 pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
1866 pOriTxD = pDestTxD ;
1869 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
1876 /* Execution of this block is not allowed when ATE is running. */
1878 #endif // RALINK_ATE //
1879 /*====================================================================*/
1881 pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket;
1884 #ifdef CONFIG_5VT_ENHANCE
1885 if (RTMP_GET_PACKET_5VT(pPacket))
1886 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE);
1888 #endif // CONFIG_5VT_ENHANCE //
1889 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
1890 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1892 //Always assign pNdisPacket as NULL after clear
1893 pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket = NULL;
1895 pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket;
1897 ASSERT(pPacket == NULL);
1900 #ifdef CONFIG_5VT_ENHANCE
1901 if (RTMP_GET_PACKET_5VT(pPacket))
1902 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE);
1904 #endif // CONFIG_5VT_ENHANCE //
1905 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
1906 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1908 //Always assign pNextNdisPacket as NULL after clear
1909 pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL;
1911 /*====================================================================*/
1913 pAd->RalinkCounters.TransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0);
1914 pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++;
1915 INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE);
1916 /* get tx_tdx_idx again */
1917 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &pTxRing->TxDmaIdx);
1918 #ifdef RT_BIG_ENDIAN
1919 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
1922 NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC));
1926 #ifdef RALINK_28xx_QA
1928 #endif // RALINK_28xx_QA //
1931 // ATE_TXCONT mode also need to send some normal frames, so let it in.
1932 // ATE_STOP must be changed not to be 0xff
1933 // to prevent it from running into this block.
1935 if ((pAd->ate.Mode & ATE_TXFRAME) && (pAd->ate.QID == QueIdx))
1937 // TxDoneCount++ has been done if QA is used.
1938 if (pAd->ate.bQATxStart == FALSE)
1940 pAd->ate.TxDoneCount++;
1942 if (((pAd->ate.TxCount - pAd->ate.TxDoneCount + 1) >= TX_RING_SIZE))
1944 /* Note : We increase TxCpuIdx here, not TxSwFreeIdx ! */
1945 INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE);
1946 #ifndef RT_BIG_ENDIAN//<==========================PETER
1947 pTxD = (PTXD_STRUC) (pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa);
1949 NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC));
1952 pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa);
1953 pOriTxD = pDestTxD ;
1956 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
1959 #ifndef RT_BIG_ENDIAN//<==========================PETER
1960 NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC));
1962 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
1966 RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx * RINGREG_DIFF, pAd->TxRing[QueIdx].TxCpuIdx);
1967 pAd->RalinkCounters.KickTxCount++;
1970 #endif // RALINK_ATE //
1980 ========================================================================
1982 Routine Description:
1983 Process TX Rings DMA Done interrupt, running in DPC level
1986 Adapter Pointer to our adapter
1991 IRQL = DISPATCH_LEVEL
1993 ========================================================================
1995 BOOLEAN RTMPHandleTxRingDmaDoneInterrupt(
1996 IN PRTMP_ADAPTER pAd,
1997 IN INT_SOURCE_CSR_STRUC TxRingBitmap)
1999 unsigned long IrqFlags;
2000 BOOLEAN bReschedule = FALSE;
2002 // Make sure Tx ring resource won't be used by other threads
2004 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
2006 if (TxRingBitmap.field.Ac0DmaDone)
2007 bReschedule = RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BE);
2009 if (TxRingBitmap.field.HccaDmaDone)
2010 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_HCCA);
2012 if (TxRingBitmap.field.Ac3DmaDone)
2013 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VO);
2015 if (TxRingBitmap.field.Ac2DmaDone)
2016 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VI);
2018 if (TxRingBitmap.field.Ac1DmaDone)
2019 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BK);
2021 // Make sure to release Tx ring resource
2022 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
2024 // Dequeue outgoing frames from TxSwQueue[] and process it
2025 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
2032 ========================================================================
2034 Routine Description:
2035 Process MGMT ring DMA done interrupt, running in DPC level
2038 pAd Pointer to our adapter
2043 IRQL = DISPATCH_LEVEL
2047 ========================================================================
2049 VOID RTMPHandleMgmtRingDmaDoneInterrupt(
2050 IN PRTMP_ADAPTER pAd)
2053 #ifdef RT_BIG_ENDIAN
2054 PTXD_STRUC pDestTxD;
2057 PNDIS_PACKET pPacket;
2059 PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing;
2061 NdisAcquireSpinLock(&pAd->MgmtRingLock);
2063 RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pMgmtRing->TxDmaIdx);
2064 while (pMgmtRing->TxSwFreeIdx!= pMgmtRing->TxDmaIdx)
2067 #ifdef RT_BIG_ENDIAN
2068 pDestTxD = (PTXD_STRUC) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa);
2071 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
2073 pTxD = (PTXD_STRUC) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa);
2076 pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket;
2081 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
2082 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
2084 pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket = NULL;
2086 pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket;
2089 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
2090 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
2092 pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket = NULL;
2093 INC_RING_INDEX(pMgmtRing->TxSwFreeIdx, MGMT_RING_SIZE);
2095 #ifdef RT_BIG_ENDIAN
2096 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
2097 WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, TRUE, TYPE_TXD);
2100 NdisReleaseSpinLock(&pAd->MgmtRingLock);
2106 ========================================================================
2108 Routine Description:
2110 Adapter Pointer to our adapter. Dequeue all power safe delayed braodcast frames after beacon.
2112 IRQL = DISPATCH_LEVEL
2114 ========================================================================
2116 VOID RTMPHandleTBTTInterrupt(
2117 IN PRTMP_ADAPTER pAd)
2120 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2128 ========================================================================
2130 Routine Description:
2132 Adapter Pointer to our adapter. Rewrite beacon content before next send-out.
2134 IRQL = DISPATCH_LEVEL
2136 ========================================================================
2138 VOID RTMPHandlePreTBTTInterrupt(
2139 IN PRTMP_ADAPTER pAd)
2142 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2144 DBGPRINT(RT_DEBUG_TRACE, ("RTMPHandlePreTBTTInterrupt...\n"));
2151 VOID RTMPHandleRxCoherentInterrupt(
2152 IN PRTMP_ADAPTER pAd)
2154 WPDMA_GLO_CFG_STRUC GloCfg;
2158 DBGPRINT(RT_DEBUG_TRACE, ("====> pAd is NULL, return.\n"));
2162 DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPHandleRxCoherentInterrupt \n"));
2164 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG , &GloCfg.word);
2166 GloCfg.field.EnTXWriteBackDDONE = 0;
2167 GloCfg.field.EnableRxDMA = 0;
2168 GloCfg.field.EnableTxDMA = 0;
2169 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
2171 RTMPRingCleanUp(pAd, QID_AC_BE);
2172 RTMPRingCleanUp(pAd, QID_AC_BK);
2173 RTMPRingCleanUp(pAd, QID_AC_VI);
2174 RTMPRingCleanUp(pAd, QID_AC_VO);
2175 RTMPRingCleanUp(pAd, QID_HCCA);
2176 RTMPRingCleanUp(pAd, QID_MGMT);
2177 RTMPRingCleanUp(pAd, QID_RX);
2179 RTMPEnableRxTx(pAd);
2181 DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPHandleRxCoherentInterrupt \n"));
2185 VOID DBGPRINT_TX_RING(
2186 IN PRTMP_ADAPTER pAd,
2190 UINT32 Ac0HwIdx = 0, Ac0SwIdx = 0, AC0freeIdx;
2194 DBGPRINT_RAW(RT_DEBUG_TRACE, ("=====================================================\n " ));
2198 RTMP_IO_READ32(pAd, TX_BASE_PTR0, &Ac0Base);
2199 RTMP_IO_READ32(pAd, TX_CTX_IDX0, &Ac0SwIdx);
2200 RTMP_IO_READ32(pAd, TX_DTX_IDX0, &Ac0HwIdx);
2201 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_BE DESCRIPTOR \n " ));
2202 for (i=0;i<TX_RING_SIZE;i++)
2204 ptemp= (PULONG)pAd->TxRing[QID_AC_BE].Cell[i].AllocVa;
2205 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
2207 DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
2210 RTMP_IO_READ32(pAd, TX_BASE_PTR1, &Ac0Base);
2211 RTMP_IO_READ32(pAd, TX_CTX_IDX1, &Ac0SwIdx);
2212 RTMP_IO_READ32(pAd, TX_DTX_IDX1, &Ac0HwIdx);
2213 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_BK DESCRIPTOR \n " ));
2214 for (i=0;i<TX_RING_SIZE;i++)
2216 ptemp= (PULONG)pAd->TxRing[QID_AC_BK].Cell[i].AllocVa;
2217 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
2219 DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
2222 RTMP_IO_READ32(pAd, TX_BASE_PTR2, &Ac0Base);
2223 RTMP_IO_READ32(pAd, TX_CTX_IDX2, &Ac0SwIdx);
2224 RTMP_IO_READ32(pAd, TX_DTX_IDX2, &Ac0HwIdx);
2225 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_VI DESCRIPTOR \n " ));
2226 for (i=0;i<TX_RING_SIZE;i++)
2228 ptemp= (PULONG)pAd->TxRing[QID_AC_VI].Cell[i].AllocVa;
2229 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
2231 DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
2234 RTMP_IO_READ32(pAd, TX_BASE_PTR3, &Ac0Base);
2235 RTMP_IO_READ32(pAd, TX_CTX_IDX3, &Ac0SwIdx);
2236 RTMP_IO_READ32(pAd, TX_DTX_IDX3, &Ac0HwIdx);
2237 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_VO DESCRIPTOR \n " ));
2238 for (i=0;i<TX_RING_SIZE;i++)
2240 ptemp= (PULONG)pAd->TxRing[QID_AC_VO].Cell[i].AllocVa;
2241 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
2243 DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
2246 RTMP_IO_READ32(pAd, TX_BASE_PTR5, &Ac0Base);
2247 RTMP_IO_READ32(pAd, TX_CTX_IDX5, &Ac0SwIdx);
2248 RTMP_IO_READ32(pAd, TX_DTX_IDX5, &Ac0HwIdx);
2249 DBGPRINT_RAW(RT_DEBUG_TRACE, (" All QID_MGMT DESCRIPTOR \n " ));
2250 for (i=0;i<MGMT_RING_SIZE;i++)
2252 ptemp= (PULONG)pAd->MgmtRing.Cell[i].AllocVa;
2253 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
2255 DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
2259 DBGPRINT_ERR(("DBGPRINT_TX_RING(Ring %d) not supported\n", QueIdx));
2262 AC0freeIdx = pAd->TxRing[QueIdx].TxSwFreeIdx;
2264 DBGPRINT(RT_DEBUG_TRACE,("TxRing%d, TX_DTX_IDX=%d, TX_CTX_IDX=%d\n", QueIdx, Ac0HwIdx, Ac0SwIdx));
2265 DBGPRINT_RAW(RT_DEBUG_TRACE,(" TxSwFreeIdx[%d]", AC0freeIdx));
2266 DBGPRINT_RAW(RT_DEBUG_TRACE,(" pending-NDIS=%ld\n", pAd->RalinkCounters.PendingNdisPacketCount));
2272 VOID DBGPRINT_RX_RING(
2273 IN PRTMP_ADAPTER pAd)
2276 UINT32 Ac0HwIdx = 0, Ac0SwIdx = 0, AC0freeIdx;
2280 DBGPRINT_RAW(RT_DEBUG_TRACE, ("=====================================================\n " ));
2281 RTMP_IO_READ32(pAd, RX_BASE_PTR, &Ac0Base);
2282 RTMP_IO_READ32(pAd, RX_CRX_IDX, &Ac0SwIdx);
2283 RTMP_IO_READ32(pAd, RX_DRX_IDX, &Ac0HwIdx);
2284 AC0freeIdx = pAd->RxRing.RxSwReadIdx;
2286 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All RX DSP \n " ));
2287 for (i=0;i<RX_RING_SIZE;i++)
2289 ptemp = (UINT32 *)pAd->RxRing.Cell[i].AllocVa;
2290 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08x: %08x: %08x: %08x\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
2292 DBGPRINT(RT_DEBUG_TRACE,("RxRing, RX_DRX_IDX=%d, RX_CRX_IDX=%d \n", Ac0HwIdx, Ac0SwIdx));
2293 DBGPRINT_RAW(RT_DEBUG_TRACE,(" RxSwReadIdx [%d]=", AC0freeIdx));
2294 DBGPRINT_RAW(RT_DEBUG_TRACE,(" pending-NDIS=%ld\n", pAd->RalinkCounters.PendingNdisPacketCount));
2298 ========================================================================
2300 Routine Description:
2301 Suspend MSDU transmission
2304 pAd Pointer to our adapter
2311 ========================================================================
2313 VOID RTMPSuspendMsduTransmission(
2314 IN PRTMP_ADAPTER pAd)
2316 DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n"));
2320 // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
2321 // use Lowbound as R66 value on ScanNextChannel(...)
2323 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue);
2325 // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)
2326 RTMPSetAGCInitValue(pAd, BW_20);
2328 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
2333 ========================================================================
2335 Routine Description:
2336 Resume MSDU transmission
2339 pAd Pointer to our adapter
2344 IRQL = DISPATCH_LEVEL
2348 ========================================================================
2350 VOID RTMPResumeMsduTransmission(
2351 IN PRTMP_ADAPTER pAd)
2353 DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
2356 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue);
2358 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
2359 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
2363 UINT deaggregate_AMSDU_announce(
2364 IN PRTMP_ADAPTER pAd,
2365 PNDIS_PACKET pPacket,
2370 USHORT SubFrameSize;
2371 PHEADER_802_3 pAMSDUsubheader;
2373 UCHAR Header802_3[14];
2375 PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP;
2376 PNDIS_PACKET pClonePacket;
2382 while (DataSize > LENGTH_802_3)
2387 pAMSDUsubheader = (PHEADER_802_3)pData;
2388 PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8);
2389 SubFrameSize = PayloadSize + LENGTH_802_3;
2392 if ((DataSize < SubFrameSize) || (PayloadSize > 1518 ))
2397 pPayload = pData + LENGTH_802_3;
2399 pSA = pData + MAC_ADDR_LEN;
2401 // convert to 802.3 header
2402 CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP);
2404 #ifdef CONFIG_STA_SUPPORT
2405 if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) )
2407 // avoid local heap overflow, use dyanamic allocation
2408 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
2409 memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize);
2410 Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize;
2411 WpaEAPOLKeyAction(pAd, Elem);
2414 #endif // CONFIG_STA_SUPPORT //
2416 #ifdef CONFIG_STA_SUPPORT
2417 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2419 if (pRemovedLLCSNAP)
2421 pPayload -= LENGTH_802_3;
2422 PayloadSize += LENGTH_802_3;
2423 NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3);
2426 #endif // CONFIG_STA_SUPPORT //
2428 pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
2431 #ifdef CONFIG_STA_SUPPORT
2432 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2433 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket));
2434 #endif // CONFIG_STA_SUPPORT //
2438 // A-MSDU has padding to multiple of 4 including subframe header.
2439 // align SubFrameSize up to multiple of 4
2440 SubFrameSize = (SubFrameSize+3)&(~0x3);
2443 if (SubFrameSize > 1528 || SubFrameSize < 32)
2448 if (DataSize > SubFrameSize)
2450 pData += SubFrameSize;
2451 DataSize -= SubFrameSize;
2460 // finally release original rx packet
2461 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
2467 UINT BA_Reorder_AMSDU_Annnounce(
2468 IN PRTMP_ADAPTER pAd,
2469 IN PNDIS_PACKET pPacket)
2475 pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
2476 DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
2478 nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
2485 ==========================================================================
2487 Look up the MAC address in the MAC table. Return NULL if not found.
2489 pEntry - pointer to the MAC entry; NULL is not found
2490 ==========================================================================
2492 MAC_TABLE_ENTRY *MacTableLookup(
2493 IN PRTMP_ADAPTER pAd,
2497 MAC_TABLE_ENTRY *pEntry = NULL;
2499 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
2500 pEntry = pAd->MacTab.Hash[HashIdx];
2502 while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh))
2504 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
2509 pEntry = pEntry->pNext;
2515 MAC_TABLE_ENTRY *MacTableInsertEntry(
2516 IN PRTMP_ADAPTER pAd,
2519 IN BOOLEAN CleanAll)
2523 MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
2526 if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
2530 #ifdef CONFIG_STA_SUPPORT
2531 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2532 if (pAd->StaCfg.BssType == BSS_INFRA)
2534 #endif // CONFIG_STA_SUPPORT //
2536 // allocate one MAC entry
2537 NdisAcquireSpinLock(&pAd->MacTabLock);
2538 for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++) // skip entry#0 so that "entry index == AID" for fast lookup
2540 // pick up the first available vacancy
2541 if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
2542 (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
2543 (pAd->MacTab.Content[i].ValidAsApCli== FALSE) &&
2544 (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
2545 #ifdef CONFIG_STA_SUPPORT
2546 #ifdef QOS_DLS_SUPPORT
2547 && (pAd->MacTab.Content[i].ValidAsDls == FALSE)
2548 #endif // QOS_DLS_SUPPORT //
2549 #endif // CONFIG_STA_SUPPORT //
2552 pEntry = &pAd->MacTab.Content[i];
2553 if (CleanAll == TRUE)
2555 pEntry->MaxSupportedRate = RATE_11;
2556 pEntry->CurrTxRate = RATE_11;
2557 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
2558 pEntry->PairwiseKey.KeyLen = 0;
2559 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
2561 #ifdef CONFIG_STA_SUPPORT
2562 #ifdef QOS_DLS_SUPPORT
2563 if (apidx >= MIN_NET_DEVICE_FOR_DLS)
2565 pEntry->ValidAsCLI = FALSE;
2566 pEntry->ValidAsWDS = FALSE;
2567 pEntry->ValidAsApCli = FALSE;
2568 pEntry->ValidAsMesh = FALSE;
2569 pEntry->ValidAsDls = TRUE;
2570 pEntry->isCached = FALSE;
2573 #endif // QOS_DLS_SUPPORT //
2574 #endif // CONFIG_STA_SUPPORT //
2577 #ifdef CONFIG_STA_SUPPORT
2578 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2580 pEntry->ValidAsCLI = TRUE;
2581 pEntry->ValidAsWDS = FALSE;
2582 pEntry->ValidAsApCli = FALSE;
2583 pEntry->ValidAsMesh = FALSE;
2584 pEntry->ValidAsDls = FALSE;
2586 #endif // CONFIG_STA_SUPPORT //
2589 pEntry->bIAmBadAtheros = FALSE;
2591 pEntry->CMTimerRunning = FALSE;
2592 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
2593 pEntry->RSNIE_Len = 0;
2594 NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
2595 pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
2597 if (pEntry->ValidAsMesh)
2598 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH);
2599 else if (pEntry->ValidAsApCli)
2600 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI);
2601 else if (pEntry->ValidAsWDS)
2602 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS);
2603 #ifdef CONFIG_STA_SUPPORT
2604 #ifdef QOS_DLS_SUPPORT
2605 else if (pEntry->ValidAsDls)
2606 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_DLS);
2607 #endif // QOS_DLS_SUPPORT //
2608 #endif // CONFIG_STA_SUPPORT //
2610 pEntry->apidx = apidx;
2614 #ifdef CONFIG_STA_SUPPORT
2615 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2617 pEntry->AuthMode = pAd->StaCfg.AuthMode;
2618 pEntry->WepStatus = pAd->StaCfg.WepStatus;
2619 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
2620 AsicRemovePairwiseKeyEntry(pAd, pEntry->apidx, (UCHAR)i);
2622 #endif // CONFIG_STA_SUPPORT //
2625 pEntry->GTKState = REKEY_NEGOTIATING;
2626 pEntry->PairwiseKey.KeyLen = 0;
2627 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
2628 #ifdef CONFIG_STA_SUPPORT
2629 if ((pAd->OpMode == OPMODE_STA) &&
2630 (pAd->StaCfg.BssType == BSS_ADHOC))
2631 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
2633 #ifdef QOS_DLS_SUPPORT
2634 if (pEntry->ValidAsDls == TRUE)
2635 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
2637 #endif //QOS_DLS_SUPPORT
2638 #endif // CONFIG_STA_SUPPORT //
2639 pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
2640 pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
2641 COPY_MAC_ADDR(pEntry->Addr, pAddr);
2642 pEntry->Sst = SST_NOT_AUTH;
2643 pEntry->AuthState = AS_NOT_AUTH;
2644 pEntry->Aid = (USHORT)i; //0;
2645 pEntry->CapabilityInfo = 0;
2646 pEntry->PsMode = PWR_ACTIVE;
2647 pEntry->PsQIdleCount = 0;
2648 pEntry->NoDataIdleCount = 0;
2649 pEntry->ContinueTxFailCnt = 0;
2650 InitializeQueueHeader(&pEntry->PsQueue);
2653 pAd->MacTab.Size ++;
2654 // Add this entry into ASIC RX WCID search table
2655 RT28XX_STA_ENTRY_ADD(pAd, pEntry);
2659 DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size));
2664 // add this MAC entry into HASH table
2667 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
2668 if (pAd->MacTab.Hash[HashIdx] == NULL)
2670 pAd->MacTab.Hash[HashIdx] = pEntry;
2674 pCurrEntry = pAd->MacTab.Hash[HashIdx];
2675 while (pCurrEntry->pNext != NULL)
2676 pCurrEntry = pCurrEntry->pNext;
2677 pCurrEntry->pNext = pEntry;
2681 NdisReleaseSpinLock(&pAd->MacTabLock);
2686 ==========================================================================
2688 Delete a specified client from MAC table
2689 ==========================================================================
2691 BOOLEAN MacTableDeleteEntry(
2692 IN PRTMP_ADAPTER pAd,
2697 MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
2700 if (wcid >= MAX_LEN_OF_MAC_TABLE)
2703 NdisAcquireSpinLock(&pAd->MacTabLock);
2705 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
2706 pEntry = &pAd->MacTab.Content[wcid];
2708 if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh
2709 #ifdef CONFIG_STA_SUPPORT
2710 #ifdef QOS_DLS_SUPPORT
2711 || pEntry->ValidAsDls
2712 #endif // QOS_DLS_SUPPORT //
2713 #endif // CONFIG_STA_SUPPORT //
2716 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
2719 // Delete this entry from ASIC on-chip WCID Table
2720 RT28XX_STA_ENTRY_MAC_RESET(pAd, wcid);
2722 #ifdef DOT11_N_SUPPORT
2723 // free resources of BA
2724 BASessionTearDownALL(pAd, pEntry->Aid);
2725 #endif // DOT11_N_SUPPORT //
2729 pProbeEntry = pAd->MacTab.Hash[HashIdx];
2730 ASSERT(pProbeEntry);
2735 if (pProbeEntry == pEntry)
2737 if (pPrevEntry == NULL)
2739 pAd->MacTab.Hash[HashIdx] = pEntry->pNext;
2743 pPrevEntry->pNext = pEntry->pNext;
2748 pPrevEntry = pProbeEntry;
2749 pProbeEntry = pProbeEntry->pNext;
2750 } while (pProbeEntry);
2753 ASSERT(pProbeEntry != NULL);
2755 RT28XX_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
2758 if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
2760 RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
2761 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
2765 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
2766 pAd->MacTab.Size --;
2767 DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size));
2771 printk("\n%s: Impossible Wcid = %d !!!!!\n", __func__, wcid);
2775 NdisReleaseSpinLock(&pAd->MacTabLock);
2777 //Reset operating mode when no Sta.
2778 if (pAd->MacTab.Size == 0)
2780 #ifdef DOT11_N_SUPPORT
2781 pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
2782 #endif // DOT11_N_SUPPORT //
2783 AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/);
2791 ==========================================================================
2793 This routine reset the entire MAC table. All packets pending in
2794 the power-saving queues are freed here.
2795 ==========================================================================
2798 IN PRTMP_ADAPTER pAd)
2802 DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
2803 //NdisAcquireSpinLock(&pAd->MacTabLock);
2805 for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
2807 RT28XX_STA_ENTRY_MAC_RESET(pAd, i);
2808 if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
2811 #ifdef DOT11_N_SUPPORT
2812 // free resources of BA
2813 BASessionTearDownALL(pAd, i);
2814 #endif // DOT11_N_SUPPORT //
2816 pAd->MacTab.Content[i].ValidAsCLI = FALSE;
2821 //AsicDelWcidTab(pAd, i);
2829 ==========================================================================
2832 IRQL = DISPATCH_LEVEL
2834 ==========================================================================
2837 IN PRTMP_ADAPTER pAd,
2838 IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
2840 IN USHORT CapabilityInfo,
2842 IN USHORT ListenIntv)
2844 COPY_MAC_ADDR(AssocReq->Addr, pAddr);
2845 // Add mask to support 802.11b mode only
2846 AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request
2847 AssocReq->Timeout = Timeout;
2848 AssocReq->ListenIntv = ListenIntv;
2853 ==========================================================================
2856 IRQL = DISPATCH_LEVEL
2858 ==========================================================================
2860 VOID DisassocParmFill(
2861 IN PRTMP_ADAPTER pAd,
2862 IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
2866 COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
2867 DisassocReq->Reason = Reason;
2872 ========================================================================
2874 Routine Description:
2875 Check the out going frame, if this is an DHCP or ARP datagram
2876 will be duplicate another frame at low data rate transmit.
2879 pAd Pointer to our adapter
2880 pPacket Pointer to outgoing Ndis frame
2883 TRUE To be duplicate at Low data rate transmit. (1mb)
2886 IRQL = DISPATCH_LEVEL
2890 MAC header + IP Header + UDP Header
2894 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
2896 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
2899 port 0x43 means Bootstrap Protocol, server.
2900 Port 0x44 means Bootstrap Protocol, client.
2902 ========================================================================
2905 BOOLEAN RTMPCheckDHCPFrame(
2906 IN PRTMP_ADAPTER pAd,
2907 IN PNDIS_PACKET pPacket)
2909 PACKET_INFO PacketInfo;
2910 ULONG NumberOfBytesRead = 0;
2911 ULONG CurrentOffset = 0;
2912 PVOID pVirtualAddress = NULL;
2913 UINT NdisBufferLength;
2916 UCHAR ByteOffset36 = 0;
2917 UCHAR ByteOffset38 = 0;
2918 BOOLEAN ReadFirstParm = TRUE;
2920 RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength);
2922 NumberOfBytesRead += NdisBufferLength;
2923 pSrc = (PUCHAR) pVirtualAddress;
2924 Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
2927 // Check DHCP & BOOTP protocol
2929 while (NumberOfBytesRead <= PacketInfo.TotalPacketLength)
2931 if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE))
2933 CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength);
2934 ByteOffset36 = *(pSrc + CurrentOffset);
2935 ReadFirstParm = FALSE;
2938 if (NumberOfBytesRead >= 37)
2940 CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength);
2941 ByteOffset38 = *(pSrc + CurrentOffset);
2948 // Check for DHCP & BOOTP protocol
2949 if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43))
2952 // 2054 (hex 0806) for ARP datagrams
2953 // if this packet is not ARP datagrams, then do nothing
2954 // ARP datagrams will also be duplicate at 1mb broadcast frames
2956 if (Protocol != 0x0806 )
2964 BOOLEAN RTMPCheckEtherType(
2965 IN PRTMP_ADAPTER pAd,
2966 IN PNDIS_PACKET pPacket)
2972 UINT16 srcPort, dstPort;
2973 BOOLEAN status = TRUE;
2976 pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
2977 pktLen = GET_OS_PKT_LEN(pPacket);
2981 RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
2983 // get Ethernet protocol field
2984 TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13];
2986 pSrcBuf += LENGTH_802_3; // Skip the Ethernet Header.
2988 if (TypeLen <= 1500)
2989 { // 802.3, 802.3 LLC
2991 DestMAC(6) + SrcMAC(6) + Lenght(2) +
2992 DSAP(1) + SSAP(1) + Control(1) +
2993 if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
2994 => + SNAP (5, OriginationID(3) + etherType(2))
2996 if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03)
2998 Sniff2BytesFromNdisBuffer(pSrcBuf, 6, &Byte0, &Byte1);
2999 RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
3000 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
3001 pSrcBuf += 8; // Skip this LLC/SNAP header
3005 //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.
3009 // If it's a VLAN packet, get the real Type/Length field.
3010 if (TypeLen == 0x8100)
3012 /* 0x8100 means VLAN packets */
3014 /* Dest. MAC Address (6-bytes) +
3015 Source MAC Address (6-bytes) +
3016 Length/Type = 802.1Q Tag Type (2-byte) +
3017 Tag Control Information (2-bytes) +
3018 Length / Type (2-bytes) +
3019 data payload (0-n bytes) +
3021 Frame Check Sequence (4-bytes) */
3023 RTMP_SET_PACKET_VLAN(pPacket, 1);
3024 Sniff2BytesFromNdisBuffer(pSrcBuf, 2, &Byte0, &Byte1);
3025 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
3027 pSrcBuf += 4; // Skip the VLAN Header.
3034 ASSERT((pktLen > 34));
3035 if (*(pSrcBuf + 9) == 0x11)
3037 ASSERT((pktLen > 34)); // 14 for ethernet header, 20 for IP header
3039 pSrcBuf += 20; // Skip the IP header
3040 srcPort = OS_NTOHS(*((UINT16 *)pSrcBuf));
3041 dstPort = OS_NTOHS(*((UINT16 *)(pSrcBuf +2)));
3043 if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44))
3044 { //It's a BOOTP/DHCP packet
3045 RTMP_SET_PACKET_DHCP(pPacket, 1);
3053 RTMP_SET_PACKET_DHCP(pPacket, 1);
3059 RTMP_SET_PACKET_EAPOL(pPacket, 1);
3073 VOID Update_Rssi_Sample(
3074 IN PRTMP_ADAPTER pAd,
3075 IN RSSI_SAMPLE *pRssi,
3076 IN PRXWI_STRUC pRxWI)
3078 CHAR rssi0 = pRxWI->RSSI0;
3079 CHAR rssi1 = pRxWI->RSSI1;
3080 CHAR rssi2 = pRxWI->RSSI2;
3084 pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0);
3085 pRssi->AvgRssi0X8 = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
3086 pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
3091 pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1);
3092 pRssi->AvgRssi1X8 = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
3093 pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
3098 pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2);
3099 pRssi->AvgRssi2X8 = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
3100 pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
3106 // Normal legacy Rx packet indication
3107 VOID Indicate_Legacy_Packet(
3108 IN PRTMP_ADAPTER pAd,
3110 IN UCHAR FromWhichBSSID)
3112 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
3113 UCHAR Header802_3[LENGTH_802_3];
3115 // 1. get 802.3 Header
3117 // a. pointer pRxBlk->pData to payload
3118 // b. modify pRxBlk->DataSize
3119 #ifdef CONFIG_STA_SUPPORT
3120 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3121 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
3122 #endif // CONFIG_STA_SUPPORT //
3124 if (pRxBlk->DataSize > MAX_RX_PKT_LEN)
3128 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
3133 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
3136 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
3139 // pass this 802.3 packet to upper layer or forward this packet to WM directly
3141 #ifdef CONFIG_STA_SUPPORT
3142 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3143 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
3144 #endif // CONFIG_STA_SUPPORT //
3149 // Normal, AMPDU or AMSDU
3150 VOID CmmRxnonRalinkFrameIndicate(
3151 IN PRTMP_ADAPTER pAd,
3153 IN UCHAR FromWhichBSSID)
3155 #ifdef DOT11_N_SUPPORT
3156 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
3158 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
3161 #endif // DOT11_N_SUPPORT //
3163 #ifdef DOT11_N_SUPPORT
3164 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
3167 Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
3170 #endif // DOT11_N_SUPPORT //
3172 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
3178 VOID CmmRxRalinkFrameIndicate(
3179 IN PRTMP_ADAPTER pAd,
3180 IN MAC_TABLE_ENTRY *pEntry,
3182 IN UCHAR FromWhichBSSID)
3184 UCHAR Header802_3[LENGTH_802_3];
3186 UINT16 Payload1Size, Payload2Size;
3188 PNDIS_PACKET pPacket2 = NULL;
3192 Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8);
3194 if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize))
3196 /* skip two byte MSDU2 len */
3198 pRxBlk->DataSize -= 2;
3203 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
3207 // get 802.3 Header and remove LLC
3208 #ifdef CONFIG_STA_SUPPORT
3209 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3210 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
3211 #endif // CONFIG_STA_SUPPORT //
3214 ASSERT(pRxBlk->pRxPacket);
3216 // Ralink Aggregation frame
3217 pAd->RalinkCounters.OneSecRxAggregationCount ++;
3218 Payload1Size = pRxBlk->DataSize - Msdu2Size;
3219 Payload2Size = Msdu2Size - LENGTH_802_3;
3221 pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
3222 #ifdef CONFIG_STA_SUPPORT
3223 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3224 pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID);
3225 #endif // CONFIG_STA_SUPPORT //
3230 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
3234 // update payload size of 1st packet
3235 pRxBlk->DataSize = Payload1Size;
3236 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
3238 #ifdef CONFIG_STA_SUPPORT
3239 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3240 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID);
3241 #endif // CONFIG_STA_SUPPORT //
3245 #ifdef CONFIG_STA_SUPPORT
3246 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3247 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
3248 #endif // CONFIG_STA_SUPPORT //
3253 #define RESET_FRAGFRAME(_fragFrame) \
3255 _fragFrame.RxSize = 0; \
3256 _fragFrame.Sequence = 0; \
3257 _fragFrame.LastFrag = 0; \
3258 _fragFrame.Flags = 0; \
3262 PNDIS_PACKET RTMPDeFragmentDataFrame(
3263 IN PRTMP_ADAPTER pAd,
3266 PHEADER_802_11 pHeader = pRxBlk->pHeader;
3267 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
3268 UCHAR *pData = pRxBlk->pData;
3269 USHORT DataSize = pRxBlk->DataSize;
3270 PNDIS_PACKET pRetPacket = NULL;
3271 UCHAR *pFragBuffer = NULL;
3272 BOOLEAN bReassDone = FALSE;
3273 UCHAR HeaderRoom = 0;
3278 HeaderRoom = pData - (UCHAR *)pHeader;
3280 // Re-assemble the fragmented packets
3281 if (pHeader->Frag == 0) // Frag. Number is 0 : First frag or only one pkt
3283 // the first pkt of fragment, record it.
3284 if (pHeader->FC.MoreFrag)
3286 ASSERT(pAd->FragFrame.pFragPacket);
3287 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
3288 pAd->FragFrame.RxSize = DataSize + HeaderRoom;
3289 NdisMoveMemory(pFragBuffer, pHeader, pAd->FragFrame.RxSize);
3290 pAd->FragFrame.Sequence = pHeader->Sequence;
3291 pAd->FragFrame.LastFrag = pHeader->Frag; // Should be 0
3292 ASSERT(pAd->FragFrame.LastFrag == 0);
3293 goto done; // end of processing this frame
3296 else //Middle & End of fragment
3298 if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
3299 (pHeader->Frag != (pAd->FragFrame.LastFrag + 1)))
3301 // Fragment is not the same sequence or out of fragment number order
3302 // Reset Fragment control blk
3303 RESET_FRAGFRAME(pAd->FragFrame);
3304 DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n"));
3305 goto done; // give up this frame
3307 else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE)
3309 // Fragment frame is too large, it exeeds the maximum frame size.
3310 // Reset Fragment control blk
3311 RESET_FRAGFRAME(pAd->FragFrame);
3312 DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
3313 goto done; // give up this frame
3317 // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.
3318 // In this case, we will dropt it.
3320 if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H)))
3322 DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag));
3323 goto done; // give up this frame
3326 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
3328 // concatenate this fragment into the re-assembly buffer
3329 NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize);
3330 pAd->FragFrame.RxSize += DataSize;
3331 pAd->FragFrame.LastFrag = pHeader->Frag; // Update fragment number
3334 if (pHeader->FC.MoreFrag == FALSE)
3341 // always release rx fragmented packet
3342 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
3344 // return defragmented packet if packet is reassembled completely
3345 // otherwise return NULL
3348 PNDIS_PACKET pNewFragPacket;
3350 // allocate a new packet buffer for fragment
3351 pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
3355 pRetPacket = pAd->FragFrame.pFragPacket;
3356 pAd->FragFrame.pFragPacket = pNewFragPacket;
3357 pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
3358 pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom;
3359 pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
3360 pRxBlk->pRxPacket = pRetPacket;
3364 RESET_FRAGFRAME(pAd->FragFrame);
3372 VOID Indicate_AMSDU_Packet(
3373 IN PRTMP_ADAPTER pAd,
3375 IN UCHAR FromWhichBSSID)
3379 update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
3380 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
3381 nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize);
3384 VOID Indicate_EAPOL_Packet(
3385 IN PRTMP_ADAPTER pAd,
3387 IN UCHAR FromWhichBSSID)
3389 MAC_TABLE_ENTRY *pEntry = NULL;
3392 #ifdef CONFIG_STA_SUPPORT
3393 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3395 pEntry = &pAd->MacTab.Content[BSSID_WCID];
3396 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
3399 #endif // CONFIG_STA_SUPPORT //
3403 DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
3405 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
3410 #define BCN_TBTT_OFFSET 64 //defer 64 us
3411 VOID ReSyncBeaconTime(
3412 IN PRTMP_ADAPTER pAd)
3418 Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
3420 pAd->TbttTickCount++;
3423 // The updated BeaconInterval Value will affect Beacon Interval after two TBTT
3424 // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
3426 if (Offset == (BCN_TBTT_OFFSET-2))
3428 BCN_TIME_CFG_STRUC csr;
3429 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
3430 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; // ASIC register in units of 1/16 TU = 64us
3431 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
3435 if (Offset == (BCN_TBTT_OFFSET-1))
3437 BCN_TIME_CFG_STRUC csr;
3439 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
3440 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU
3441 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);