2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 *************************************************************************
28 #include "../rt_config.h"
30 #define MAX_TX_IN_TBTT (16)
33 UCHAR SNAP_802_1H[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
34 UCHAR SNAP_BRIDGE_TUNNEL[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8};
35 // Add Cisco Aironet SNAP heade for CCX2 support
36 UCHAR SNAP_AIRONET[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00};
37 UCHAR CKIP_LLC_SNAP[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02};
38 UCHAR EAPOL_LLC_SNAP[]= {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e};
39 UCHAR EAPOL[] = {0x88, 0x8e};
40 UCHAR TPID[] = {0x81, 0x00}; /* VLAN related */
42 UCHAR IPX[] = {0x81, 0x37};
43 UCHAR APPLE_TALK[] = {0x80, 0xf3};
44 UCHAR RateIdToPlcpSignal[12] = {
45 0, /* RATE_1 */ 1, /* RATE_2 */ 2, /* RATE_5_5 */ 3, /* RATE_11 */ // see BBP spec
46 11, /* RATE_6 */ 15, /* RATE_9 */ 10, /* RATE_12 */ 14, /* RATE_18 */ // see IEEE802.11a-1999 p.14
47 9, /* RATE_24 */ 13, /* RATE_36 */ 8, /* RATE_48 */ 12 /* RATE_54 */ }; // see IEEE802.11a-1999 p.14
49 UCHAR OfdmSignalToRateId[16] = {
50 RATE_54, RATE_54, RATE_54, RATE_54, // OFDM PLCP Signal = 0, 1, 2, 3 respectively
51 RATE_54, RATE_54, RATE_54, RATE_54, // OFDM PLCP Signal = 4, 5, 6, 7 respectively
52 RATE_48, RATE_24, RATE_12, RATE_6, // OFDM PLCP Signal = 8, 9, 10, 11 respectively
53 RATE_54, RATE_36, RATE_18, RATE_9, // OFDM PLCP Signal = 12, 13, 14, 15 respectively
56 UCHAR OfdmRateToRxwiMCS[12] = {
58 0, 1, 2, 3, // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3
59 4, 5, 6, 7, // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7
61 UCHAR RxwiMCSToOfdmRate[12] = {
62 RATE_6, RATE_9, RATE_12, RATE_18,
63 RATE_24, RATE_36, RATE_48, RATE_54, // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3
64 4, 5, 6, 7, // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7
67 char* MCSToMbps[] = {"1Mbps","2Mbps","5.5Mbps","11Mbps","06Mbps","09Mbps","12Mbps","18Mbps","24Mbps","36Mbps","48Mbps","54Mbps","MM-0","MM-1","MM-2","MM-3","MM-4","MM-5","MM-6","MM-7","MM-8","MM-9","MM-10","MM-11","MM-12","MM-13","MM-14","MM-15","MM-32","ee1","ee2","ee3"};
69 UCHAR default_cwmin[]={CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1, CW_MIN_IN_BITS-2};
70 UCHAR default_sta_aifsn[]={3,7,2,2};
72 UCHAR MapUserPriorityToAccessCategory[8] = {QID_AC_BE, QID_AC_BK, QID_AC_BK, QID_AC_BE, QID_AC_VI, QID_AC_VI, QID_AC_VO, QID_AC_VO};
76 ========================================================================
79 API for MLME to transmit management frame to AP (BSS Mode)
80 or station (IBSS Mode)
83 pAd Pointer to our adapter
84 pData Pointer to the outgoing 802.11 frame
85 Length Size of outgoing management frame
97 ========================================================================
99 NDIS_STATUS MiniportMMRequest(
100 IN PRTMP_ADAPTER pAd,
105 PNDIS_PACKET pPacket;
106 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
109 unsigned long IrqFlags = 0;
112 UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN];
114 ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
120 IrqState = pAd->irq_disabled;
122 if ((pAd->MACVersion == 0x28600100) && (!IrqState))
123 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
128 // Reset is in progress, stop immediately
129 if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
130 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)||
131 !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
133 Status = NDIS_STATUS_FAILURE;
137 // Check Free priority queue
138 // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing.
141 if (pAd->MACVersion == 0x28600100)
143 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
147 FreeNum = GET_MGMTRING_FREENO(pAd);
152 // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870
153 NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE));
154 Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE), pData, Length);
155 if (Status != NDIS_STATUS_SUCCESS)
157 DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
161 //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
162 //pAd->CommonCfg.MlmeRate = RATE_2;
165 Status = MlmeHardTransmit(pAd, QueIdx, pPacket);
166 if (Status != NDIS_STATUS_SUCCESS)
167 RTMPFreeNdisPacket(pAd, pPacket);
171 pAd->RalinkCounters.MgmtRingFullCount++;
172 DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n",
173 QueIdx, pAd->RalinkCounters.MgmtRingFullCount));
180 if ((pAd->MACVersion == 0x28600100) && (!IrqState))
181 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
189 NDIS_STATUS MiniportMMRequestUnlock(
190 IN PRTMP_ADAPTER pAd,
195 PNDIS_PACKET pPacket;
196 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
203 ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
207 // Reset is in progress, stop immediately
208 if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
209 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)||
210 !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
212 Status = NDIS_STATUS_FAILURE;
216 // Check Free priority queue
217 // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing.
219 if (pAd->MACVersion == 0x28600100)
221 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
222 SW_TX_IDX = pAd->TxRing[QueIdx].TxCpuIdx;
223 pTxD = (PTXD_STRUC) pAd->TxRing[QueIdx].Cell[SW_TX_IDX].AllocVa;
227 FreeNum = GET_MGMTRING_FREENO(pAd);
228 SW_TX_IDX = pAd->MgmtRing.TxCpuIdx;
229 pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[SW_TX_IDX].AllocVa;
233 NdisZeroMemory(&TXWI, TXWI_SIZE);
234 Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&TXWI, TXWI_SIZE, pData, Length);
235 if (Status != NDIS_STATUS_SUCCESS)
237 DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
241 Status = MlmeHardTransmit(pAd, QueIdx, pPacket);
242 if (Status != NDIS_STATUS_SUCCESS)
243 RTMPFreeNdisPacket(pAd, pPacket);
247 pAd->RalinkCounters.MgmtRingFullCount++;
248 DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing\n", QueIdx));
260 ========================================================================
263 Copy frame from waiting queue into relative ring buffer and set
264 appropriate ASIC register to kick hardware transmit function
267 pAd Pointer to our adapter
268 pBuffer Pointer to memory of outgoing frame
269 Length Size of outgoing management frame
277 IRQL = DISPATCH_LEVEL
281 ========================================================================
283 NDIS_STATUS MlmeHardTransmit(
284 IN PRTMP_ADAPTER pAd,
286 IN PNDIS_PACKET pPacket)
288 if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
290 return NDIS_STATUS_FAILURE;
294 if ( pAd->MACVersion == 0x28600100 )
295 return MlmeHardTransmitTxRing(pAd,QueIdx,pPacket);
298 return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
304 NDIS_STATUS MlmeHardTransmitTxRing(
305 IN PRTMP_ADAPTER pAd,
307 IN PNDIS_PACKET pPacket)
309 PACKET_INFO PacketInfo;
317 PHEADER_802_11 pHeader_802_11;
318 BOOLEAN bAckRequired, bInsertTimestamp;
321 ULONG SwIdx = pAd->TxRing[QueIdx].TxCpuIdx;
322 PTXWI_STRUC pFirstTxWI;
324 MAC_TABLE_ENTRY *pMacEntry = NULL;
327 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
329 if (pSrcBufVA == NULL)
331 // The buffer shouldn't be NULL
332 return NDIS_STATUS_FAILURE;
335 // Make sure MGMT ring resource won't be used by other threads
336 //NdisAcquireSpinLock(&pAd->TxRingLock);
338 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
342 //NdisReleaseSpinLock(&pAd->TxRingLock);
343 return NDIS_STATUS_FAILURE;
346 SwIdx = pAd->TxRing[QueIdx].TxCpuIdx;
348 #ifndef RT_BIG_ENDIAN
349 pTxD = (PTXD_STRUC) pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa;
351 pDestTxD = (PTXD_STRUC)pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa;
354 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
357 if (pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket)
359 printk("MlmeHardTransmit Error\n");
360 return NDIS_STATUS_FAILURE;
364 #ifdef CONFIG_STA_SUPPORT
365 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
367 // outgoing frame always wakeup PHY to prevent frame lost
368 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
369 AsicForceWakeup(pAd, TRUE);
371 #endif // CONFIG_STA_SUPPORT //
372 pFirstTxWI =(PTXWI_STRUC)pSrcBufVA;
374 pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXWI_SIZE);
375 if (pHeader_802_11->Addr1[0] & 0x01)
377 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
381 MlmeRate = pAd->CommonCfg.MlmeRate;
384 if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
385 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
387 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
390 // Verify Mlme rate for a / g bands.
391 if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
395 // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
396 // Snice it's been set to 0 while on MgtMacHeaderInit
397 // By the way this will cause frame to be send on PWR_SAVE failed.
400 // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
401 #ifdef CONFIG_STA_SUPPORT
402 // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
403 if (pHeader_802_11->FC.Type != BTYPE_DATA)
405 if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_REQ) || !(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
407 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
411 pHeader_802_11->FC.PwrMgmt = pAd->CommonCfg.bAPSDForcePowerSave;
414 #endif // CONFIG_STA_SUPPORT //
416 bInsertTimestamp = FALSE;
417 if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
419 bAckRequired = FALSE;
421 else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
423 if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
425 bAckRequired = FALSE;
426 pHeader_802_11->Duration = 0;
431 pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
432 if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
434 bInsertTimestamp = TRUE;
438 pHeader_802_11->Sequence = pAd->Sequence++;
439 if (pAd->Sequence > 0xfff)
441 // Before radar detection done, mgmt frame can not be sent but probe req
442 // Because we need to use probe req to trigger driver to send probe req in passive scan
443 if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
444 && (pAd->CommonCfg.bIEEE80211H == 1)
445 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
447 DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
448 return (NDIS_STATUS_FAILURE);
452 RTMPFrameEndianChange(pAd, (PUCHAR)pHeader_802_11, DIR_WRITE, FALSE);
455 // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
456 // should always has only one ohysical buffer, and the whole frame size equals
457 // to the first scatter buffer size
460 // Initialize TX Descriptor
461 // For inter-frame gap, the number is for this frame and next frame
462 // For MLME rate, we will fix as 2Mb to match other vendor's implement
464 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
465 // Only beacon use Nseq=TRUE. So here we use Nseq=FALSE.
466 if (pMacEntry == NULL)
468 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
469 0, RESERVED_WCID, (SrcBufLen - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
473 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
474 bInsertTimestamp, FALSE, bAckRequired, FALSE,
475 0, pMacEntry->Aid, (SrcBufLen - TXWI_SIZE),
476 pMacEntry->MaxHTPhyMode.field.MCS, 0,
477 (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
478 IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
481 pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket = pPacket;
482 pAd->TxRing[QueIdx].Cell[SwIdx].pNextNdisPacket = NULL;
484 RTMPWIEndianChange((PUCHAR)pFirstTxWI, TYPE_TXWI);
486 SrcBufPA = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE);
489 RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_EDCA);
492 pTxD->SDLen0 = SrcBufLen;
494 pTxD->SDPtr0 = SrcBufPA;
498 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
499 WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
502 pAd->RalinkCounters.KickTxCount++;
503 pAd->RalinkCounters.OneSecTxDoneCount++;
505 // Increase TX_CTX_IDX, but write to register later.
506 INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE);
508 RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx*0x10, pAd->TxRing[QueIdx].TxCpuIdx);
510 return NDIS_STATUS_SUCCESS;
515 NDIS_STATUS MlmeHardTransmitMgmtRing(
516 IN PRTMP_ADAPTER pAd,
518 IN PNDIS_PACKET pPacket)
520 PACKET_INFO PacketInfo;
523 PHEADER_802_11 pHeader_802_11;
524 BOOLEAN bAckRequired, bInsertTimestamp;
526 PTXWI_STRUC pFirstTxWI;
527 MAC_TABLE_ENTRY *pMacEntry = NULL;
529 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
530 RTMP_SEM_LOCK(&pAd->MgmtRingLock);
533 if (pSrcBufVA == NULL)
535 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
536 return NDIS_STATUS_FAILURE;
539 #ifdef CONFIG_STA_SUPPORT
540 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
542 // outgoing frame always wakeup PHY to prevent frame lost
543 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
544 AsicForceWakeup(pAd, TRUE);
546 #endif // CONFIG_STA_SUPPORT //
548 pFirstTxWI = (PTXWI_STRUC)(pSrcBufVA + TXINFO_SIZE);
549 pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); //TXWI_SIZE);
551 if (pHeader_802_11->Addr1[0] & 0x01)
553 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
557 MlmeRate = pAd->CommonCfg.MlmeRate;
560 // Verify Mlme rate for a / g bands.
561 if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
564 if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
565 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
567 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
570 #ifdef CONFIG_STA_SUPPORT
571 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
573 // Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode.
574 if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED
575 #ifdef DOT11_N_SUPPORT
576 || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED
577 #endif // DOT11_N_SUPPORT //
580 if (pAd->LatchRfRegs.Channel > 14)
581 pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
583 pAd->CommonCfg.MlmeTransmit.field.MODE = 0;
586 #endif // CONFIG_STA_SUPPORT //
589 // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
590 // Snice it's been set to 0 while on MgtMacHeaderInit
591 // By the way this will cause frame to be send on PWR_SAVE failed.
593 // pHeader_802_11->FC.PwrMgmt = 0; // (pAd->StaCfg.Psm == PWR_SAVE);
595 // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
596 #ifdef CONFIG_STA_SUPPORT
597 // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
598 if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL))
600 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
601 (pHeader_802_11->FC.SubType == SUBTYPE_ACTION))
602 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
604 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
606 #endif // CONFIG_STA_SUPPORT //
608 bInsertTimestamp = FALSE;
609 if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
611 #ifdef CONFIG_STA_SUPPORT
612 //Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue.
613 if ((pAd->OpMode == OPMODE_STA) && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL))
615 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
617 #endif // CONFIG_STA_SUPPORT //
618 bAckRequired = FALSE;
620 else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
622 if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
624 bAckRequired = FALSE;
625 pHeader_802_11->Duration = 0;
630 pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
631 if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
633 bInsertTimestamp = TRUE;
638 pHeader_802_11->Sequence = pAd->Sequence++;
639 if (pAd->Sequence >0xfff)
642 // Before radar detection done, mgmt frame can not be sent but probe req
643 // Because we need to use probe req to trigger driver to send probe req in passive scan
644 if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
645 && (pAd->CommonCfg.bIEEE80211H == 1)
646 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
648 DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
649 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
650 return (NDIS_STATUS_FAILURE);
654 RTMPFrameEndianChange(pAd, (PUCHAR)pHeader_802_11, DIR_WRITE, FALSE);
658 // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
659 // should always has only one ohysical buffer, and the whole frame size equals
660 // to the first scatter buffer size
663 // Initialize TX Descriptor
664 // For inter-frame gap, the number is for this frame and next frame
665 // For MLME rate, we will fix as 2Mb to match other vendor's implement
667 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
668 if (pMacEntry == NULL)
670 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
671 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
675 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
676 bInsertTimestamp, FALSE, bAckRequired, FALSE,
677 0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE),
678 pMacEntry->MaxHTPhyMode.field.MCS, 0,
679 (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
680 IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
684 RTMPWIEndianChange((PUCHAR)pFirstTxWI, TYPE_TXWI);
687 // Now do hardware-depened kick out.
688 HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen);
690 // Make sure to release MGMT ring resource
691 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
692 return NDIS_STATUS_SUCCESS;
696 /********************************************************************************
698 New DeQueue Procedures.
700 ********************************************************************************/
702 #define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \
704 if (bIntContext == FALSE) \
705 RTMP_IRQ_LOCK((lock), IrqFlags); \
708 #define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \
710 if (bIntContext == FALSE) \
711 RTMP_IRQ_UNLOCK((lock), IrqFlags); \
715 ========================================================================
716 Tx Path design algorithm:
717 Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal),
718 Specific Packet Type. Following show the classification rule and policy for each kinds of packets.
719 Classification Rule=>
720 Multicast: (*addr1 & 0x01) == 0x01
721 Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc.
722 11N Rate : If peer support HT
723 (1).AMPDU -- If TXBA is negotiated.
724 (2).AMSDU -- If AMSDU is capable for both peer and ourself.
725 *). AMSDU can embedded in a AMPDU, but now we didn't support it.
726 (3).Normal -- Other packets which send as 11n rate.
728 B/G Rate : If peer is b/g only.
729 (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6
730 (2).Normal -- Other packets which send as b/g rate.
732 The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
734 Classified Packet Handle Rule=>
736 No ACK, //pTxBlk->bAckRequired = FALSE;
737 No WMM, //pTxBlk->bWMM = FALSE;
738 No piggyback, //pTxBlk->bPiggyBack = FALSE;
739 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
740 Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use
741 the same policy to handle it.
742 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
745 No piggyback, //pTxBlk->bPiggyBack = FALSE;
757 ========================================================================
759 static UCHAR TxPktClassification(
760 IN RTMP_ADAPTER *pAd,
761 IN PNDIS_PACKET pPacket)
763 UCHAR TxFrameType = TX_UNKOWN_FRAME;
765 MAC_TABLE_ENTRY *pMacEntry = NULL;
766 #ifdef DOT11_N_SUPPORT
767 BOOLEAN bHTRate = FALSE;
768 #endif // DOT11_N_SUPPORT //
770 Wcid = RTMP_GET_PACKET_WCID(pPacket);
771 if (Wcid == MCAST_WCID)
772 { // Handle for RA is Broadcast/Multicast Address.
773 return TX_MCAST_FRAME;
776 // Handle for unicast packets
777 pMacEntry = &pAd->MacTab.Content[Wcid];
778 if (RTMP_GET_PACKET_LOWRATE(pPacket))
779 { // It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame
780 TxFrameType = TX_LEGACY_FRAME;
782 #ifdef DOT11_N_SUPPORT
783 else if (IS_HT_RATE(pMacEntry))
784 { // it's a 11n capable packet
786 // Depends on HTPhyMode to check if the peer support the HTRate transmission.
787 // Currently didn't support A-MSDU embedded in A-MPDU
789 if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE))
790 TxFrameType = TX_LEGACY_FRAME;
791 #ifdef UAPSD_AP_SUPPORT
792 else if (RTMP_GET_PACKET_EOSP(pPacket))
793 TxFrameType = TX_LEGACY_FRAME;
794 #endif // UAPSD_AP_SUPPORT //
795 else if((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0)
796 return TX_AMPDU_FRAME;
797 else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED))
798 return TX_AMSDU_FRAME;
800 TxFrameType = TX_LEGACY_FRAME;
802 #endif // DOT11_N_SUPPORT //
804 { // it's a legacy b/g packet.
805 if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) &&
806 (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) &&
807 (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
808 { // if peer support Ralink Aggregation, we use it.
809 TxFrameType = TX_RALINK_FRAME;
813 TxFrameType = TX_LEGACY_FRAME;
817 // Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU.
818 if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) && (TxFrameType == TX_LEGACY_FRAME))
819 TxFrameType = TX_FRAG_FRAME;
825 BOOLEAN RTMP_FillTxBlkInfo(
826 IN RTMP_ADAPTER *pAd,
829 PACKET_INFO PacketInfo;
830 PNDIS_PACKET pPacket;
831 PMAC_TABLE_ENTRY pMacEntry = NULL;
833 pPacket = pTxBlk->pPacket;
834 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
836 pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket);
837 pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket);
838 pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket);
839 pTxBlk->FrameGap = IFS_HTTXOP; // ASIC determine Frame Gap
841 if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket))
842 TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame);
844 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame);
846 // Default to clear this flag
847 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS);
850 if (pTxBlk->Wcid == MCAST_WCID)
852 pTxBlk->pMacEntry = NULL;
854 #ifdef MCAST_RATE_SPECIFIC
855 PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket);
856 if (((*pDA & 0x01) == 0x01) && (*pDA != 0xff))
857 pTxBlk->pTransmit = &pAd->CommonCfg.MCastPhyMode;
859 #endif // MCAST_RATE_SPECIFIC //
860 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
863 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); // AckRequired = FALSE, when broadcast packet in Adhoc mode.
864 //TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate);
865 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag);
866 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
867 if (RTMP_GET_PACKET_MOREDATA(pPacket))
869 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
875 pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
876 pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode;
878 pMacEntry = pTxBlk->pMacEntry;
881 // For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK.
882 if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK)
883 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
885 TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired);
889 #ifdef CONFIG_STA_SUPPORT
890 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
893 // If support WMM, enable it.
894 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
895 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM);
897 #endif // CONFIG_STA_SUPPORT //
900 if (pTxBlk->TxFrameType == TX_LEGACY_FRAME)
902 if ( (RTMP_GET_PACKET_LOWRATE(pPacket)) ||
903 ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1)))
904 { // Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate.
905 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
906 #ifdef DOT11_N_SUPPORT
907 // Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it???
908 if (IS_HT_STA(pTxBlk->pMacEntry) &&
909 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) &&
910 ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)))
912 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
913 TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS);
915 #endif // DOT11_N_SUPPORT //
918 #ifdef DOT11_N_SUPPORT
919 if ( (IS_HT_RATE(pMacEntry) == FALSE) &&
920 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE)))
921 { // Currently piggy-back only support when peer is operate in b/g mode.
922 TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack);
924 #endif // DOT11_N_SUPPORT //
926 if (RTMP_GET_PACKET_MOREDATA(pPacket))
928 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
930 #ifdef UAPSD_AP_SUPPORT
931 if (RTMP_GET_PACKET_EOSP(pPacket))
933 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP);
935 #endif // UAPSD_AP_SUPPORT //
937 else if (pTxBlk->TxFrameType == TX_FRAG_FRAME)
939 TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag);
942 pMacEntry->DebugTxCount++;
949 BOOLEAN CanDoAggregateTransmit(
950 IN RTMP_ADAPTER *pAd,
951 IN NDIS_PACKET *pPacket,
955 //printk("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType);
957 if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
960 if (RTMP_GET_PACKET_DHCP(pPacket) ||
961 RTMP_GET_PACKET_EAPOL(pPacket) ||
962 RTMP_GET_PACKET_WAI(pPacket))
965 if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) &&
966 ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100)))
967 { // For AMSDU, allow the packets with total length < max-amsdu size
971 if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) &&
972 (pTxBlk->TxPacketList.Number == 2))
973 { // For RALINK-Aggregation, allow two frames in one batch.
977 #ifdef CONFIG_STA_SUPPORT
978 if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP
981 #endif // CONFIG_STA_SUPPORT //
988 ========================================================================
991 To do the enqueue operation and extract the first item of waiting
992 list. If a number of available shared memory segments could meet
993 the request of extracted item, the extracted item will be fragmented
994 into shared memory segments.
997 pAd Pointer to our adapter
998 pQueue Pointer to Waiting Queue
1003 IRQL = DISPATCH_LEVEL
1007 ========================================================================
1009 VOID RTMPDeQueuePacket(
1010 IN PRTMP_ADAPTER pAd,
1011 IN BOOLEAN bIntContext,
1012 IN UCHAR QIdx, /* BulkOutPipeId */
1013 IN UCHAR Max_Tx_Packets)
1015 PQUEUE_ENTRY pEntry = NULL;
1016 PNDIS_PACKET pPacket;
1017 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
1019 PQUEUE_HEADER pQueue;
1020 ULONG FreeNumber[NUM_OF_TX_RING];
1021 UCHAR QueIdx, sQIdx, eQIdx;
1022 unsigned long IrqFlags = 0;
1023 BOOLEAN hasTxDesc = FALSE;
1029 RtmpDiagStruct *pDiagStruct = &pAd->DiagStruct;
1033 if (QIdx == NUM_OF_TX_RING)
1036 eQIdx = 3; // 4 ACs, start from 0.
1040 sQIdx = eQIdx = QIdx;
1043 for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++)
1047 RT28XX_START_DEQUEUE(pAd, QueIdx, IrqFlags);
1050 firstRound = ((QueIdx == 0) ? TRUE : FALSE);
1051 #endif // DBG_DIAGNOSE //
1055 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |
1056 fRTMP_ADAPTER_RADIO_OFF |
1057 fRTMP_ADAPTER_RESET_IN_PROGRESS |
1058 fRTMP_ADAPTER_HALT_IN_PROGRESS |
1059 fRTMP_ADAPTER_NIC_NOT_EXIST))))
1061 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
1065 if (Count >= Max_Tx_Packets)
1068 DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1069 if (&pAd->TxSwQueue[QueIdx] == NULL)
1072 if (firstRound == TRUE)
1073 pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][0]++;
1074 #endif // DBG_DIAGNOSE //
1075 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1080 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
1083 if (firstRound == TRUE)
1085 UCHAR txDescNumLevel, txSwQNumLevel;
1087 txDescNumLevel = (TX_RING_SIZE - FreeNumber[QueIdx]); // Number of occupied hw desc.
1088 txDescNumLevel = ((txDescNumLevel <=15) ? txDescNumLevel : 15);
1089 pDiagStruct->TxDescCnt[pDiagStruct->ArrayCurIdx][txDescNumLevel]++;
1091 txSwQNumLevel = ((pAd->TxSwQueue[QueIdx].Number <=7) ? pAd->TxSwQueue[QueIdx].Number : 8);
1092 pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][txSwQNumLevel]++;
1096 #endif // DBG_DIAGNOSE //
1098 if (FreeNumber[QueIdx] <= 5)
1100 // free Tx(QueIdx) resources
1101 RTMPFreeTXDUponTxDmaDone(pAd, QueIdx);
1102 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
1106 // probe the Queue Head
1107 pQueue = &pAd->TxSwQueue[QueIdx];
1108 if ((pEntry = pQueue->Head) == NULL)
1110 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1115 NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK));
1116 pTxBlk->QueIdx = QueIdx;
1118 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
1120 // Early check to make sure we have enoguh Tx Resource.
1121 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
1124 pAd->PrivateInfo.TxRingFullCnt++;
1126 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1131 pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
1132 pEntry = RemoveHeadQueue(pQueue);
1133 pTxBlk->TotalFrameNum++;
1134 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
1135 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
1136 pTxBlk->pPacket = pPacket;
1137 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
1139 if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME)
1141 // Enhance SW Aggregation Mechanism
1142 if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType))
1144 InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
1145 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1150 if((pEntry = pQueue->Head) == NULL)
1153 // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation.
1154 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
1155 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
1156 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
1157 if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE))
1160 //Remove the packet from the TxSwQueue and insert into pTxBlk
1161 pEntry = RemoveHeadQueue(pQueue);
1163 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
1164 pTxBlk->TotalFrameNum++;
1165 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
1166 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
1167 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
1170 if (pTxBlk->TxPacketList.Number == 1)
1171 pTxBlk->TxFrameType = TX_LEGACY_FRAME;
1175 Count += pTxBlk->TxPacketList.Number;
1177 // Do HardTransmit now.
1178 #ifdef CONFIG_STA_SUPPORT
1179 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1180 Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
1181 #endif // CONFIG_STA_SUPPORT //
1184 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1185 // static rate also need NICUpdateFifoStaCounters() function.
1186 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
1187 NICUpdateFifoStaCounters(pAd);
1191 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
1195 if ((pAd->blockQueueTab[QueIdx].SwTxQueueBlockFlag == TRUE)
1196 && (pAd->TxSwQueue[QueIdx].Number < 1))
1198 releaseNetIf(&pAd->blockQueueTab[QueIdx]);
1200 #endif // BLOCK_NET_IF //
1208 ========================================================================
1210 Routine Description:
1211 Calculates the duration which is required to transmit out frames
1212 with given size and specified rate.
1215 pAd Pointer to our adapter
1217 Size Frame size in units of byte
1220 Duration number in units of usec
1222 IRQL = PASSIVE_LEVEL
1223 IRQL = DISPATCH_LEVEL
1227 ========================================================================
1229 USHORT RTMPCalcDuration(
1230 IN PRTMP_ADAPTER pAd,
1236 if (Rate < RATE_FIRST_OFDM_RATE) // CCK
1238 if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED))
1239 Duration = 96; // 72+24 preamble+plcp
1241 Duration = 192; // 144+48 preamble+plcp
1243 Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]);
1244 if ((Size << 4) % RateIdTo500Kbps[Rate])
1247 else if (Rate <= RATE_LAST_OFDM_RATE)// OFDM rates
1249 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
1250 Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
1251 if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
1256 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
1259 return (USHORT)Duration;
1264 ========================================================================
1266 Routine Description:
1267 Calculates the duration which is required to transmit out frames
1268 with given size and specified rate.
1271 pTxWI Pointer to head of each MPDU to HW.
1272 Ack Setting for Ack requirement bit
1273 Fragment Setting for Fragment bit
1274 RetryMode Setting for retry mode
1275 Ifs Setting for IFS gap
1276 Rate Setting for transmit rate
1277 Service Setting for service
1279 TxPreamble Short or Long preamble when using CCK rates
1280 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1285 IRQL = PASSIVE_LEVEL
1286 IRQL = DISPATCH_LEVEL
1288 See also : BASmartHardTransmit() !!!
1290 ========================================================================
1293 IN PRTMP_ADAPTER pAd,
1294 IN PTXWI_STRUC pOutTxWI,
1297 IN BOOLEAN InsTimestamp,
1300 IN BOOLEAN NSeq, // HW new a sequence.
1309 IN HTTRANSMIT_SETTING *pTransmit)
1311 PMAC_TABLE_ENTRY pMac = NULL;
1315 if (WCID < MAX_LEN_OF_MAC_TABLE)
1316 pMac = &pAd->MacTab.Content[WCID];
1319 // Always use Long preamble before verifiation short preamble functionality works well.
1320 // Todo: remove the following line if short preamble functionality works
1322 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1323 NdisZeroMemory(&TxWI, TXWI_SIZE);
1328 pTxWI->CFACK = CFACK;
1329 pTxWI->TS= InsTimestamp;
1330 pTxWI->AMPDU = AMPDU;
1332 pTxWI->txop= Txopmode;
1335 // John tune the performace with Intel Client in 20 MHz performance
1336 #ifdef DOT11_N_SUPPORT
1337 BASize = pAd->CommonCfg.TxBASize;
1341 pTxWI->BAWinSize = BASize;
1342 pTxWI->ShortGI = pTransmit->field.ShortGI;
1343 pTxWI->STBC = pTransmit->field.STBC;
1344 #endif // DOT11_N_SUPPORT //
1346 pTxWI->WirelessCliID = WCID;
1347 pTxWI->MPDUtotalByteCount = Length;
1348 pTxWI->PacketId = PID;
1350 // If CCK or OFDM, BW must be 20
1351 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1352 #ifdef DOT11N_DRAFT3
1354 pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1355 #endif // DOT11N_DRAFT3 //
1357 pTxWI->MCS = pTransmit->field.MCS;
1358 pTxWI->PHYMODE = pTransmit->field.MODE;
1359 pTxWI->CFACK = CfAck;
1361 #ifdef DOT11_N_SUPPORT
1364 if (pAd->CommonCfg.bMIMOPSEnable)
1366 if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1368 // Dynamic MIMO Power Save Mode
1371 else if (pMac->MmpsMode == MMPS_STATIC)
1373 // Static MIMO Power Save Mode
1374 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1381 //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;
1382 if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled))
1384 pTxWI->MpduDensity = 7;
1388 pTxWI->MpduDensity = pMac->MpduDensity;
1391 #endif // DOT11_N_SUPPORT //
1393 pTxWI->PacketId = pTxWI->MCS;
1394 NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC));
1398 VOID RTMPWriteTxWI_Data(
1399 IN PRTMP_ADAPTER pAd,
1400 IN OUT PTXWI_STRUC pTxWI,
1403 HTTRANSMIT_SETTING *pTransmit;
1404 PMAC_TABLE_ENTRY pMacEntry;
1405 #ifdef DOT11_N_SUPPORT
1407 #endif // DOT11_N_SUPPORT //
1412 pTransmit = pTxBlk->pTransmit;
1413 pMacEntry = pTxBlk->pMacEntry;
1417 // Always use Long preamble before verifiation short preamble functionality works well.
1418 // Todo: remove the following line if short preamble functionality works
1420 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1421 NdisZeroMemory(pTxWI, TXWI_SIZE);
1423 pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1424 pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1425 pTxWI->txop = pTxBlk->FrameGap;
1427 #ifdef CONFIG_STA_SUPPORT
1428 #ifdef QOS_DLS_SUPPORT
1430 (pAd->StaCfg.BssType == BSS_INFRA) &&
1431 (pMacEntry->ValidAsDls == TRUE))
1432 pTxWI->WirelessCliID = BSSID_WCID;
1434 #endif // QOS_DLS_SUPPORT //
1435 #endif // CONFIG_STA_SUPPORT //
1436 pTxWI->WirelessCliID = pTxBlk->Wcid;
1438 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1439 pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
1441 // If CCK or OFDM, BW must be 20
1442 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1443 #ifdef DOT11_N_SUPPORT
1444 #ifdef DOT11N_DRAFT3
1446 pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1447 #endif // DOT11N_DRAFT3 //
1448 pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
1450 // John tune the performace with Intel Client in 20 MHz performance
1451 BASize = pAd->CommonCfg.TxBASize;
1452 if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry))
1454 UCHAR RABAOriIdx = 0; //The RA's BA Originator table index.
1456 RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
1457 BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1460 pTxWI->TxBF = pTransmit->field.TxBF;
1461 pTxWI->BAWinSize = BASize;
1462 pTxWI->ShortGI = pTransmit->field.ShortGI;
1463 pTxWI->STBC = pTransmit->field.STBC;
1464 #endif // DOT11_N_SUPPORT //
1466 pTxWI->MCS = pTransmit->field.MCS;
1467 pTxWI->PHYMODE = pTransmit->field.MODE;
1469 #ifdef DOT11_N_SUPPORT
1472 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1474 // Dynamic MIMO Power Save Mode
1477 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1479 // Static MIMO Power Save Mode
1480 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1487 if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled))
1489 pTxWI->MpduDensity = 7;
1493 pTxWI->MpduDensity = pMacEntry->MpduDensity;
1496 #endif // DOT11_N_SUPPORT //
1499 if (pTxBlk->QueIdx== 0)
1501 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1502 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1504 #endif // DBG_DIAGNOSE //
1506 // for rate adapation
1507 pTxWI->PacketId = pTxWI->MCS;
1511 VOID RTMPWriteTxWI_Cache(
1512 IN PRTMP_ADAPTER pAd,
1513 IN OUT PTXWI_STRUC pTxWI,
1516 PHTTRANSMIT_SETTING pTransmit;
1517 PMAC_TABLE_ENTRY pMacEntry;
1522 pMacEntry = pTxBlk->pMacEntry;
1523 pTransmit = pTxBlk->pTransmit;
1525 if (pMacEntry->bAutoTxRateSwitch)
1527 pTxWI->txop = IFS_HTTXOP;
1529 // If CCK or OFDM, BW must be 20
1530 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1531 pTxWI->ShortGI = pTransmit->field.ShortGI;
1532 pTxWI->STBC = pTransmit->field.STBC;
1534 pTxWI->MCS = pTransmit->field.MCS;
1535 pTxWI->PHYMODE = pTransmit->field.MODE;
1537 // set PID for TxRateSwitching
1538 pTxWI->PacketId = pTransmit->field.MCS;
1541 #ifdef DOT11_N_SUPPORT
1542 pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE);
1545 #ifdef DOT11N_DRAFT3
1547 pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1548 #endif // DOT11N_DRAFT3 //
1550 if (pAd->CommonCfg.bMIMOPSEnable)
1552 // MIMO Power Save Mode
1553 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1555 // Dynamic MIMO Power Save Mode
1558 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1560 // Static MIMO Power Save Mode
1561 if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7))
1568 #endif // DOT11_N_SUPPORT //
1571 if (pTxBlk->QueIdx== 0)
1573 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1574 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1576 #endif // DBG_DIAGNOSE //
1578 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1584 ========================================================================
1586 Routine Description:
1587 Calculates the duration which is required to transmit out frames
1588 with given size and specified rate.
1591 pTxD Pointer to transmit descriptor
1592 Ack Setting for Ack requirement bit
1593 Fragment Setting for Fragment bit
1594 RetryMode Setting for retry mode
1595 Ifs Setting for IFS gap
1596 Rate Setting for transmit rate
1597 Service Setting for service
1599 TxPreamble Short or Long preamble when using CCK rates
1600 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1605 IRQL = PASSIVE_LEVEL
1606 IRQL = DISPATCH_LEVEL
1608 ========================================================================
1610 VOID RTMPWriteTxDescriptor(
1611 IN PRTMP_ADAPTER pAd,
1617 // Always use Long preamble before verifiation short preamble functionality works well.
1618 // Todo: remove the following line if short preamble functionality works
1620 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1622 pTxD->WIV = (bWIV) ? 1: 0;
1623 pTxD->QSEL= (QueueSEL);
1624 if (pAd->bGenOneHCCA == TRUE)
1625 pTxD->QSEL= FIFO_HCCA;
1630 // should be called only when -
1631 // 1. MEADIA_CONNECTED
1632 // 2. AGGREGATION_IN_USED
1633 // 3. Fragmentation not in used
1634 // 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible
1635 BOOLEAN TxFrameIsAggregatible(
1636 IN PRTMP_ADAPTER pAd,
1637 IN PUCHAR pPrevAddr1,
1641 // can't aggregate EAPOL (802.1x) frame
1642 if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1645 // can't aggregate multicast/broadcast frame
1646 if (p8023hdr[0] & 0x01)
1649 if (INFRA_ON(pAd)) // must be unicast to AP
1651 else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA
1659 ========================================================================
1661 Routine Description:
1662 Check the MSDU Aggregation policy
1663 1.HT aggregation is A-MSDU
1664 2.legaacy rate aggregation is software aggregation by Ralink.
1672 ========================================================================
1674 BOOLEAN PeerIsAggreOn(
1675 IN PRTMP_ADAPTER pAd,
1677 IN PMAC_TABLE_ENTRY pMacEntry)
1679 ULONG AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
1681 if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags))
1683 #ifdef DOT11_N_SUPPORT
1684 if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX)
1688 #endif // DOT11_N_SUPPORT //
1690 #ifdef AGGREGATION_SUPPORT
1691 if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
1692 { // legacy Ralink Aggregation support
1695 #endif // AGGREGATION_SUPPORT //
1704 ========================================================================
1706 Routine Description:
1707 Check and fine the packet waiting in SW queue with highest priority
1710 pAd Pointer to our adapter
1713 pQueue Pointer to Waiting Queue
1715 IRQL = DISPATCH_LEVEL
1719 ========================================================================
1721 PQUEUE_HEADER RTMPCheckTxSwQueue(
1722 IN PRTMP_ADAPTER pAd,
1728 Number = pAd->TxSwQueue[QID_AC_BK].Number
1729 + pAd->TxSwQueue[QID_AC_BE].Number
1730 + pAd->TxSwQueue[QID_AC_VI].Number
1731 + pAd->TxSwQueue[QID_AC_VO].Number
1732 + pAd->TxSwQueue[QID_HCCA].Number;
1734 if (pAd->TxSwQueue[QID_AC_VO].Head != NULL)
1736 *pQueIdx = QID_AC_VO;
1737 return (&pAd->TxSwQueue[QID_AC_VO]);
1739 else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL)
1741 *pQueIdx = QID_AC_VI;
1742 return (&pAd->TxSwQueue[QID_AC_VI]);
1744 else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL)
1746 *pQueIdx = QID_AC_BE;
1747 return (&pAd->TxSwQueue[QID_AC_BE]);
1749 else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL)
1751 *pQueIdx = QID_AC_BK;
1752 return (&pAd->TxSwQueue[QID_AC_BK]);
1754 else if (pAd->TxSwQueue[QID_HCCA].Head != NULL)
1756 *pQueIdx = QID_HCCA;
1757 return (&pAd->TxSwQueue[QID_HCCA]);
1760 // No packet pending in Tx Sw queue
1761 *pQueIdx = QID_AC_BK;
1768 BOOLEAN RTMPFreeTXDUponTxDmaDone(
1769 IN PRTMP_ADAPTER pAd,
1772 PRTMP_TX_RING pTxRing;
1774 #ifdef RT_BIG_ENDIAN
1775 PTXD_STRUC pDestTxD;
1777 PNDIS_PACKET pPacket;
1779 TXD_STRUC TxD, *pOriTxD;
1781 BOOLEAN bReschedule = FALSE;
1784 ASSERT(QueIdx < NUM_OF_TX_RING);
1785 pTxRing = &pAd->TxRing[QueIdx];
1787 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF, &pTxRing->TxDmaIdx);
1788 while (pTxRing->TxSwFreeIdx != pTxRing->TxDmaIdx)
1791 #ifdef RALINK_28xx_QA
1792 PHEADER_802_11 pHeader80211;
1794 if ((ATE_ON(pAd)) && (pAd->ate.bQATxStart == TRUE))
1796 if (pAd->ate.QID == QueIdx)
1798 pAd->ate.TxDoneCount++;
1799 //pAd->ate.Repeat++;
1800 pAd->RalinkCounters.KickTxCount++;
1802 /* always use QID_AC_BE and FIFO_EDCA */
1803 ASSERT(pAd->ate.QID == 0);
1807 #ifndef RT_BIG_ENDIAN
1808 pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
1810 NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC));
1813 pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
1814 pOriTxD = pDestTxD ;
1817 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
1821 pHeader80211 = pTxRing->Cell[pTxRing->TxSwFreeIdx].DmaBuf.AllocVa + sizeof(TXWI_STRUC);
1822 #ifdef RT_BIG_ENDIAN
1823 RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_READ, FALSE);
1825 pHeader80211->Sequence = ++pAd->ate.seq;
1826 #ifdef RT_BIG_ENDIAN
1827 RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_WRITE, FALSE);
1830 if ((pAd->ate.bQATxStart == TRUE) && (pAd->ate.Mode & ATE_TXFRAME) && (pAd->ate.TxDoneCount < pAd->ate.TxCount))
1832 pAd->RalinkCounters.TransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0);
1833 pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++;
1834 INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE);
1835 /* get tx_tdx_idx again */
1836 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &pTxRing->TxDmaIdx);
1839 else if ((pAd->ate.TxStatus == 1)/* or (pAd->ate.bQATxStart == TRUE) ??? */ && (pAd->ate.TxDoneCount == pAd->ate.TxCount))//<========================PETER
1841 DBGPRINT(RT_DEBUG_TRACE,("all Tx is done\n"));
1842 // Tx status enters idle mode.
1843 pAd->ate.TxStatus = 0;
1845 else if (!(pAd->ate.Mode & ATE_TXFRAME))
1847 /* not complete sending yet, but someone press the Stop TX botton. */
1848 DBGPRINT(RT_DEBUG_ERROR,("not complete sending yet, but someone pressed the Stop TX bottom\n"));
1849 DBGPRINT(RT_DEBUG_ERROR,("pAd->ate.Mode = 0x%02x\n", pAd->ate.Mode));
1853 DBGPRINT(RT_DEBUG_OFF,("pTxRing->TxSwFreeIdx = %d\n", pTxRing->TxSwFreeIdx));
1855 #ifndef RT_BIG_ENDIAN
1856 NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC));
1858 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
1860 #endif // RT_BIG_ENDIAN //
1862 INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE);
1866 #endif // RALINK_28xx_QA //
1867 #endif // RALINK_ATE //
1869 // static rate also need NICUpdateFifoStaCounters() function.
1870 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
1871 NICUpdateFifoStaCounters(pAd);
1873 /* Note : If (pAd->ate.bQATxStart == TRUE), we will never reach here. */
1875 #ifndef RT_BIG_ENDIAN
1876 pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
1878 NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC));
1881 pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
1882 pOriTxD = pDestTxD ;
1885 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
1892 /* Execution of this block is not allowed when ATE is running. */
1894 #endif // RALINK_ATE //
1895 /*====================================================================*/
1897 pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket;
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 pNdisPacket as NULL after clear
1909 pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket = NULL;
1911 pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket;
1913 ASSERT(pPacket == NULL);
1916 #ifdef CONFIG_5VT_ENHANCE
1917 if (RTMP_GET_PACKET_5VT(pPacket))
1918 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE);
1920 #endif // CONFIG_5VT_ENHANCE //
1921 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
1922 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1924 //Always assign pNextNdisPacket as NULL after clear
1925 pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL;
1927 /*====================================================================*/
1929 pAd->RalinkCounters.TransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0);
1930 pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++;
1931 INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE);
1932 /* get tx_tdx_idx again */
1933 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &pTxRing->TxDmaIdx);
1934 #ifdef RT_BIG_ENDIAN
1935 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
1938 NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC));
1942 #ifdef RALINK_28xx_QA
1944 #endif // RALINK_28xx_QA //
1947 // ATE_TXCONT mode also need to send some normal frames, so let it in.
1948 // ATE_STOP must be changed not to be 0xff
1949 // to prevent it from running into this block.
1951 if ((pAd->ate.Mode & ATE_TXFRAME) && (pAd->ate.QID == QueIdx))
1953 // TxDoneCount++ has been done if QA is used.
1954 if (pAd->ate.bQATxStart == FALSE)
1956 pAd->ate.TxDoneCount++;
1958 if (((pAd->ate.TxCount - pAd->ate.TxDoneCount + 1) >= TX_RING_SIZE))
1960 /* Note : We increase TxCpuIdx here, not TxSwFreeIdx ! */
1961 INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE);
1962 #ifndef RT_BIG_ENDIAN//<==========================PETER
1963 pTxD = (PTXD_STRUC) (pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa);
1965 NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC));
1968 pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa);
1969 pOriTxD = pDestTxD ;
1972 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
1975 #ifndef RT_BIG_ENDIAN//<==========================PETER
1976 NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC));
1978 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
1982 RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx * RINGREG_DIFF, pAd->TxRing[QueIdx].TxCpuIdx);
1983 pAd->RalinkCounters.KickTxCount++;
1986 #endif // RALINK_ATE //
1996 ========================================================================
1998 Routine Description:
1999 Process TX Rings DMA Done interrupt, running in DPC level
2002 Adapter Pointer to our adapter
2007 IRQL = DISPATCH_LEVEL
2009 ========================================================================
2011 BOOLEAN RTMPHandleTxRingDmaDoneInterrupt(
2012 IN PRTMP_ADAPTER pAd,
2013 IN INT_SOURCE_CSR_STRUC TxRingBitmap)
2015 unsigned long IrqFlags;
2016 BOOLEAN bReschedule = FALSE;
2018 // Make sure Tx ring resource won't be used by other threads
2020 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
2022 if (TxRingBitmap.field.Ac0DmaDone)
2023 bReschedule = RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BE);
2025 if (TxRingBitmap.field.HccaDmaDone)
2026 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_HCCA);
2028 if (TxRingBitmap.field.Ac3DmaDone)
2029 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VO);
2031 if (TxRingBitmap.field.Ac2DmaDone)
2032 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VI);
2034 if (TxRingBitmap.field.Ac1DmaDone)
2035 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BK);
2037 // Make sure to release Tx ring resource
2038 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
2040 // Dequeue outgoing frames from TxSwQueue[] and process it
2041 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
2048 ========================================================================
2050 Routine Description:
2051 Process MGMT ring DMA done interrupt, running in DPC level
2054 pAd Pointer to our adapter
2059 IRQL = DISPATCH_LEVEL
2063 ========================================================================
2065 VOID RTMPHandleMgmtRingDmaDoneInterrupt(
2066 IN PRTMP_ADAPTER pAd)
2069 #ifdef RT_BIG_ENDIAN
2070 PTXD_STRUC pDestTxD;
2073 PNDIS_PACKET pPacket;
2075 PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing;
2077 NdisAcquireSpinLock(&pAd->MgmtRingLock);
2079 RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pMgmtRing->TxDmaIdx);
2080 while (pMgmtRing->TxSwFreeIdx!= pMgmtRing->TxDmaIdx)
2083 #ifdef RT_BIG_ENDIAN
2084 pDestTxD = (PTXD_STRUC) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa);
2087 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
2089 pTxD = (PTXD_STRUC) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa);
2092 pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket;
2097 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
2098 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
2100 pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket = NULL;
2102 pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket;
2105 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
2106 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
2108 pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket = NULL;
2109 INC_RING_INDEX(pMgmtRing->TxSwFreeIdx, MGMT_RING_SIZE);
2111 #ifdef RT_BIG_ENDIAN
2112 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
2113 WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, TRUE, TYPE_TXD);
2116 NdisReleaseSpinLock(&pAd->MgmtRingLock);
2122 ========================================================================
2124 Routine Description:
2126 Adapter Pointer to our adapter. Dequeue all power safe delayed braodcast frames after beacon.
2128 IRQL = DISPATCH_LEVEL
2130 ========================================================================
2132 VOID RTMPHandleTBTTInterrupt(
2133 IN PRTMP_ADAPTER pAd)
2136 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2144 ========================================================================
2146 Routine Description:
2148 Adapter Pointer to our adapter. Rewrite beacon content before next send-out.
2150 IRQL = DISPATCH_LEVEL
2152 ========================================================================
2154 VOID RTMPHandlePreTBTTInterrupt(
2155 IN PRTMP_ADAPTER pAd)
2158 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2160 DBGPRINT(RT_DEBUG_TRACE, ("RTMPHandlePreTBTTInterrupt...\n"));
2167 VOID RTMPHandleRxCoherentInterrupt(
2168 IN PRTMP_ADAPTER pAd)
2170 WPDMA_GLO_CFG_STRUC GloCfg;
2174 DBGPRINT(RT_DEBUG_TRACE, ("====> pAd is NULL, return.\n"));
2178 DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPHandleRxCoherentInterrupt \n"));
2180 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG , &GloCfg.word);
2182 GloCfg.field.EnTXWriteBackDDONE = 0;
2183 GloCfg.field.EnableRxDMA = 0;
2184 GloCfg.field.EnableTxDMA = 0;
2185 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
2187 RTMPRingCleanUp(pAd, QID_AC_BE);
2188 RTMPRingCleanUp(pAd, QID_AC_BK);
2189 RTMPRingCleanUp(pAd, QID_AC_VI);
2190 RTMPRingCleanUp(pAd, QID_AC_VO);
2191 RTMPRingCleanUp(pAd, QID_HCCA);
2192 RTMPRingCleanUp(pAd, QID_MGMT);
2193 RTMPRingCleanUp(pAd, QID_RX);
2195 RTMPEnableRxTx(pAd);
2197 DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPHandleRxCoherentInterrupt \n"));
2201 VOID DBGPRINT_TX_RING(
2202 IN PRTMP_ADAPTER pAd,
2206 UINT32 Ac0HwIdx = 0, Ac0SwIdx = 0, AC0freeIdx;
2210 DBGPRINT_RAW(RT_DEBUG_TRACE, ("=====================================================\n " ));
2214 RTMP_IO_READ32(pAd, TX_BASE_PTR0, &Ac0Base);
2215 RTMP_IO_READ32(pAd, TX_CTX_IDX0, &Ac0SwIdx);
2216 RTMP_IO_READ32(pAd, TX_DTX_IDX0, &Ac0HwIdx);
2217 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_BE DESCRIPTOR \n " ));
2218 for (i=0;i<TX_RING_SIZE;i++)
2220 ptemp= (PULONG)pAd->TxRing[QID_AC_BE].Cell[i].AllocVa;
2221 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
2223 DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
2226 RTMP_IO_READ32(pAd, TX_BASE_PTR1, &Ac0Base);
2227 RTMP_IO_READ32(pAd, TX_CTX_IDX1, &Ac0SwIdx);
2228 RTMP_IO_READ32(pAd, TX_DTX_IDX1, &Ac0HwIdx);
2229 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_BK DESCRIPTOR \n " ));
2230 for (i=0;i<TX_RING_SIZE;i++)
2232 ptemp= (PULONG)pAd->TxRing[QID_AC_BK].Cell[i].AllocVa;
2233 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
2235 DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
2238 RTMP_IO_READ32(pAd, TX_BASE_PTR2, &Ac0Base);
2239 RTMP_IO_READ32(pAd, TX_CTX_IDX2, &Ac0SwIdx);
2240 RTMP_IO_READ32(pAd, TX_DTX_IDX2, &Ac0HwIdx);
2241 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_VI DESCRIPTOR \n " ));
2242 for (i=0;i<TX_RING_SIZE;i++)
2244 ptemp= (PULONG)pAd->TxRing[QID_AC_VI].Cell[i].AllocVa;
2245 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
2247 DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
2250 RTMP_IO_READ32(pAd, TX_BASE_PTR3, &Ac0Base);
2251 RTMP_IO_READ32(pAd, TX_CTX_IDX3, &Ac0SwIdx);
2252 RTMP_IO_READ32(pAd, TX_DTX_IDX3, &Ac0HwIdx);
2253 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_VO DESCRIPTOR \n " ));
2254 for (i=0;i<TX_RING_SIZE;i++)
2256 ptemp= (PULONG)pAd->TxRing[QID_AC_VO].Cell[i].AllocVa;
2257 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
2259 DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
2262 RTMP_IO_READ32(pAd, TX_BASE_PTR5, &Ac0Base);
2263 RTMP_IO_READ32(pAd, TX_CTX_IDX5, &Ac0SwIdx);
2264 RTMP_IO_READ32(pAd, TX_DTX_IDX5, &Ac0HwIdx);
2265 DBGPRINT_RAW(RT_DEBUG_TRACE, (" All QID_MGMT DESCRIPTOR \n " ));
2266 for (i=0;i<MGMT_RING_SIZE;i++)
2268 ptemp= (PULONG)pAd->MgmtRing.Cell[i].AllocVa;
2269 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
2271 DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
2275 DBGPRINT_ERR(("DBGPRINT_TX_RING(Ring %d) not supported\n", QueIdx));
2278 AC0freeIdx = pAd->TxRing[QueIdx].TxSwFreeIdx;
2280 DBGPRINT(RT_DEBUG_TRACE,("TxRing%d, TX_DTX_IDX=%d, TX_CTX_IDX=%d\n", QueIdx, Ac0HwIdx, Ac0SwIdx));
2281 DBGPRINT_RAW(RT_DEBUG_TRACE,(" TxSwFreeIdx[%d]", AC0freeIdx));
2282 DBGPRINT_RAW(RT_DEBUG_TRACE,(" pending-NDIS=%ld\n", pAd->RalinkCounters.PendingNdisPacketCount));
2288 VOID DBGPRINT_RX_RING(
2289 IN PRTMP_ADAPTER pAd)
2292 UINT32 Ac0HwIdx = 0, Ac0SwIdx = 0, AC0freeIdx;
2296 DBGPRINT_RAW(RT_DEBUG_TRACE, ("=====================================================\n " ));
2297 RTMP_IO_READ32(pAd, RX_BASE_PTR, &Ac0Base);
2298 RTMP_IO_READ32(pAd, RX_CRX_IDX, &Ac0SwIdx);
2299 RTMP_IO_READ32(pAd, RX_DRX_IDX, &Ac0HwIdx);
2300 AC0freeIdx = pAd->RxRing.RxSwReadIdx;
2302 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All RX DSP \n " ));
2303 for (i=0;i<RX_RING_SIZE;i++)
2305 ptemp = (UINT32 *)pAd->RxRing.Cell[i].AllocVa;
2306 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08x: %08x: %08x: %08x\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
2308 DBGPRINT(RT_DEBUG_TRACE,("RxRing, RX_DRX_IDX=%d, RX_CRX_IDX=%d \n", Ac0HwIdx, Ac0SwIdx));
2309 DBGPRINT_RAW(RT_DEBUG_TRACE,(" RxSwReadIdx [%d]=", AC0freeIdx));
2310 DBGPRINT_RAW(RT_DEBUG_TRACE,(" pending-NDIS=%ld\n", pAd->RalinkCounters.PendingNdisPacketCount));
2315 ========================================================================
2317 Routine Description:
2318 Suspend MSDU transmission
2321 pAd Pointer to our adapter
2328 ========================================================================
2330 VOID RTMPSuspendMsduTransmission(
2331 IN PRTMP_ADAPTER pAd)
2333 DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n"));
2337 // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
2338 // use Lowbound as R66 value on ScanNextChannel(...)
2340 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue);
2342 // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)
2343 RTMPSetAGCInitValue(pAd, BW_20);
2345 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
2350 ========================================================================
2352 Routine Description:
2353 Resume MSDU transmission
2356 pAd Pointer to our adapter
2361 IRQL = DISPATCH_LEVEL
2365 ========================================================================
2367 VOID RTMPResumeMsduTransmission(
2368 IN PRTMP_ADAPTER pAd)
2370 DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
2373 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue);
2375 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
2376 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
2380 UINT deaggregate_AMSDU_announce(
2381 IN PRTMP_ADAPTER pAd,
2382 PNDIS_PACKET pPacket,
2387 USHORT SubFrameSize;
2388 PHEADER_802_3 pAMSDUsubheader;
2390 UCHAR Header802_3[14];
2392 PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP;
2393 PNDIS_PACKET pClonePacket;
2399 while (DataSize > LENGTH_802_3)
2404 pAMSDUsubheader = (PHEADER_802_3)pData;
2405 PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8);
2406 SubFrameSize = PayloadSize + LENGTH_802_3;
2409 if ((DataSize < SubFrameSize) || (PayloadSize > 1518 ))
2414 pPayload = pData + LENGTH_802_3;
2416 pSA = pData + MAC_ADDR_LEN;
2418 // convert to 802.3 header
2419 CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP);
2421 #ifdef CONFIG_STA_SUPPORT
2422 if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) )
2424 // avoid local heap overflow, use dyanamic allocation
2425 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
2426 memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize);
2427 Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize;
2428 WpaEAPOLKeyAction(pAd, Elem);
2431 #endif // CONFIG_STA_SUPPORT //
2433 #ifdef CONFIG_STA_SUPPORT
2434 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2436 if (pRemovedLLCSNAP)
2438 pPayload -= LENGTH_802_3;
2439 PayloadSize += LENGTH_802_3;
2440 NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3);
2443 #endif // CONFIG_STA_SUPPORT //
2445 pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
2448 #ifdef CONFIG_STA_SUPPORT
2449 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2450 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket));
2451 #endif // CONFIG_STA_SUPPORT //
2455 // A-MSDU has padding to multiple of 4 including subframe header.
2456 // align SubFrameSize up to multiple of 4
2457 SubFrameSize = (SubFrameSize+3)&(~0x3);
2460 if (SubFrameSize > 1528 || SubFrameSize < 32)
2465 if (DataSize > SubFrameSize)
2467 pData += SubFrameSize;
2468 DataSize -= SubFrameSize;
2477 // finally release original rx packet
2478 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
2484 UINT BA_Reorder_AMSDU_Annnounce(
2485 IN PRTMP_ADAPTER pAd,
2486 IN PNDIS_PACKET pPacket)
2492 pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
2493 DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
2495 nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
2502 ==========================================================================
2504 Look up the MAC address in the MAC table. Return NULL if not found.
2506 pEntry - pointer to the MAC entry; NULL is not found
2507 ==========================================================================
2509 MAC_TABLE_ENTRY *MacTableLookup(
2510 IN PRTMP_ADAPTER pAd,
2514 MAC_TABLE_ENTRY *pEntry = NULL;
2516 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
2517 pEntry = pAd->MacTab.Hash[HashIdx];
2519 while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh))
2521 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
2526 pEntry = pEntry->pNext;
2532 MAC_TABLE_ENTRY *MacTableInsertEntry(
2533 IN PRTMP_ADAPTER pAd,
2536 IN BOOLEAN CleanAll)
2540 MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
2543 if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
2547 #ifdef CONFIG_STA_SUPPORT
2548 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2549 if (pAd->StaCfg.BssType == BSS_INFRA)
2551 #endif // CONFIG_STA_SUPPORT //
2553 // allocate one MAC entry
2554 NdisAcquireSpinLock(&pAd->MacTabLock);
2555 for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++) // skip entry#0 so that "entry index == AID" for fast lookup
2557 // pick up the first available vacancy
2558 if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
2559 (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
2560 (pAd->MacTab.Content[i].ValidAsApCli== FALSE) &&
2561 (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
2562 #ifdef CONFIG_STA_SUPPORT
2563 #ifdef QOS_DLS_SUPPORT
2564 && (pAd->MacTab.Content[i].ValidAsDls == FALSE)
2565 #endif // QOS_DLS_SUPPORT //
2566 #endif // CONFIG_STA_SUPPORT //
2569 pEntry = &pAd->MacTab.Content[i];
2570 if (CleanAll == TRUE)
2572 pEntry->MaxSupportedRate = RATE_11;
2573 pEntry->CurrTxRate = RATE_11;
2574 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
2575 pEntry->PairwiseKey.KeyLen = 0;
2576 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
2578 #ifdef CONFIG_STA_SUPPORT
2579 #ifdef QOS_DLS_SUPPORT
2580 if (apidx >= MIN_NET_DEVICE_FOR_DLS)
2582 pEntry->ValidAsCLI = FALSE;
2583 pEntry->ValidAsWDS = FALSE;
2584 pEntry->ValidAsApCli = FALSE;
2585 pEntry->ValidAsMesh = FALSE;
2586 pEntry->ValidAsDls = TRUE;
2587 pEntry->isCached = FALSE;
2590 #endif // QOS_DLS_SUPPORT //
2591 #endif // CONFIG_STA_SUPPORT //
2594 #ifdef CONFIG_STA_SUPPORT
2595 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2597 pEntry->ValidAsCLI = TRUE;
2598 pEntry->ValidAsWDS = FALSE;
2599 pEntry->ValidAsApCli = FALSE;
2600 pEntry->ValidAsMesh = FALSE;
2601 pEntry->ValidAsDls = FALSE;
2603 #endif // CONFIG_STA_SUPPORT //
2606 pEntry->bIAmBadAtheros = FALSE;
2608 pEntry->CMTimerRunning = FALSE;
2609 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
2610 pEntry->RSNIE_Len = 0;
2611 NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
2612 pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
2614 if (pEntry->ValidAsMesh)
2615 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH);
2616 else if (pEntry->ValidAsApCli)
2617 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI);
2618 else if (pEntry->ValidAsWDS)
2619 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS);
2620 #ifdef CONFIG_STA_SUPPORT
2621 #ifdef QOS_DLS_SUPPORT
2622 else if (pEntry->ValidAsDls)
2623 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_DLS);
2624 #endif // QOS_DLS_SUPPORT //
2625 #endif // CONFIG_STA_SUPPORT //
2627 pEntry->apidx = apidx;
2631 #ifdef CONFIG_STA_SUPPORT
2632 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2634 pEntry->AuthMode = pAd->StaCfg.AuthMode;
2635 pEntry->WepStatus = pAd->StaCfg.WepStatus;
2636 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
2638 AsicRemovePairwiseKeyEntry(pAd, pEntry->apidx, (UCHAR)i);
2641 #endif // CONFIG_STA_SUPPORT //
2644 pEntry->GTKState = REKEY_NEGOTIATING;
2645 pEntry->PairwiseKey.KeyLen = 0;
2646 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
2647 #ifdef CONFIG_STA_SUPPORT
2648 if ((pAd->OpMode == OPMODE_STA) &&
2649 (pAd->StaCfg.BssType == BSS_ADHOC))
2650 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
2652 #ifdef QOS_DLS_SUPPORT
2653 if (pEntry->ValidAsDls == TRUE)
2654 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
2656 #endif //QOS_DLS_SUPPORT
2657 #endif // CONFIG_STA_SUPPORT //
2658 pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
2659 pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
2660 COPY_MAC_ADDR(pEntry->Addr, pAddr);
2661 pEntry->Sst = SST_NOT_AUTH;
2662 pEntry->AuthState = AS_NOT_AUTH;
2663 pEntry->Aid = (USHORT)i; //0;
2664 pEntry->CapabilityInfo = 0;
2665 pEntry->PsMode = PWR_ACTIVE;
2666 pEntry->PsQIdleCount = 0;
2667 pEntry->NoDataIdleCount = 0;
2668 pEntry->ContinueTxFailCnt = 0;
2669 InitializeQueueHeader(&pEntry->PsQueue);
2672 pAd->MacTab.Size ++;
2673 // Add this entry into ASIC RX WCID search table
2674 RT28XX_STA_ENTRY_ADD(pAd, pEntry);
2678 DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size));
2683 // add this MAC entry into HASH table
2686 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
2687 if (pAd->MacTab.Hash[HashIdx] == NULL)
2689 pAd->MacTab.Hash[HashIdx] = pEntry;
2693 pCurrEntry = pAd->MacTab.Hash[HashIdx];
2694 while (pCurrEntry->pNext != NULL)
2695 pCurrEntry = pCurrEntry->pNext;
2696 pCurrEntry->pNext = pEntry;
2700 NdisReleaseSpinLock(&pAd->MacTabLock);
2705 ==========================================================================
2707 Delete a specified client from MAC table
2708 ==========================================================================
2710 BOOLEAN MacTableDeleteEntry(
2711 IN PRTMP_ADAPTER pAd,
2716 MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
2719 if (wcid >= MAX_LEN_OF_MAC_TABLE)
2722 NdisAcquireSpinLock(&pAd->MacTabLock);
2724 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
2725 pEntry = &pAd->MacTab.Content[wcid];
2727 if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh
2728 #ifdef CONFIG_STA_SUPPORT
2729 #ifdef QOS_DLS_SUPPORT
2730 || pEntry->ValidAsDls
2731 #endif // QOS_DLS_SUPPORT //
2732 #endif // CONFIG_STA_SUPPORT //
2735 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
2738 // Delete this entry from ASIC on-chip WCID Table
2739 RT28XX_STA_ENTRY_MAC_RESET(pAd, wcid);
2741 #ifdef DOT11_N_SUPPORT
2742 // free resources of BA
2743 BASessionTearDownALL(pAd, pEntry->Aid);
2744 #endif // DOT11_N_SUPPORT //
2748 pProbeEntry = pAd->MacTab.Hash[HashIdx];
2749 ASSERT(pProbeEntry);
2754 if (pProbeEntry == pEntry)
2756 if (pPrevEntry == NULL)
2758 pAd->MacTab.Hash[HashIdx] = pEntry->pNext;
2762 pPrevEntry->pNext = pEntry->pNext;
2767 pPrevEntry = pProbeEntry;
2768 pProbeEntry = pProbeEntry->pNext;
2769 } while (pProbeEntry);
2772 ASSERT(pProbeEntry != NULL);
2774 RT28XX_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
2777 if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
2779 RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
2780 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
2784 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
2785 pAd->MacTab.Size --;
2786 DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size));
2790 printk("\n%s: Impossible Wcid = %d !!!!!\n", __FUNCTION__, wcid);
2794 NdisReleaseSpinLock(&pAd->MacTabLock);
2796 //Reset operating mode when no Sta.
2797 if (pAd->MacTab.Size == 0)
2799 #ifdef DOT11_N_SUPPORT
2800 pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
2801 #endif // DOT11_N_SUPPORT //
2802 AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/);
2810 ==========================================================================
2812 This routine reset the entire MAC table. All packets pending in
2813 the power-saving queues are freed here.
2814 ==========================================================================
2817 IN PRTMP_ADAPTER pAd)
2821 DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
2822 //NdisAcquireSpinLock(&pAd->MacTabLock);
2824 for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
2827 RT28XX_STA_ENTRY_MAC_RESET(pAd, i);
2829 if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
2832 #ifdef DOT11_N_SUPPORT
2833 // free resources of BA
2834 BASessionTearDownALL(pAd, i);
2835 #endif // DOT11_N_SUPPORT //
2837 pAd->MacTab.Content[i].ValidAsCLI = FALSE;
2842 //AsicDelWcidTab(pAd, i);
2850 ==========================================================================
2853 IRQL = DISPATCH_LEVEL
2855 ==========================================================================
2858 IN PRTMP_ADAPTER pAd,
2859 IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
2861 IN USHORT CapabilityInfo,
2863 IN USHORT ListenIntv)
2865 COPY_MAC_ADDR(AssocReq->Addr, pAddr);
2866 // Add mask to support 802.11b mode only
2867 AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request
2868 AssocReq->Timeout = Timeout;
2869 AssocReq->ListenIntv = ListenIntv;
2874 ==========================================================================
2877 IRQL = DISPATCH_LEVEL
2879 ==========================================================================
2881 VOID DisassocParmFill(
2882 IN PRTMP_ADAPTER pAd,
2883 IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
2887 COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
2888 DisassocReq->Reason = Reason;
2893 ========================================================================
2895 Routine Description:
2896 Check the out going frame, if this is an DHCP or ARP datagram
2897 will be duplicate another frame at low data rate transmit.
2900 pAd Pointer to our adapter
2901 pPacket Pointer to outgoing Ndis frame
2904 TRUE To be duplicate at Low data rate transmit. (1mb)
2907 IRQL = DISPATCH_LEVEL
2911 MAC header + IP Header + UDP Header
2915 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
2917 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
2920 port 0x43 means Bootstrap Protocol, server.
2921 Port 0x44 means Bootstrap Protocol, client.
2923 ========================================================================
2926 BOOLEAN RTMPCheckDHCPFrame(
2927 IN PRTMP_ADAPTER pAd,
2928 IN PNDIS_PACKET pPacket)
2930 PACKET_INFO PacketInfo;
2931 ULONG NumberOfBytesRead = 0;
2932 ULONG CurrentOffset = 0;
2933 PVOID pVirtualAddress = NULL;
2934 UINT NdisBufferLength;
2937 UCHAR ByteOffset36 = 0;
2938 UCHAR ByteOffset38 = 0;
2939 BOOLEAN ReadFirstParm = TRUE;
2941 RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength);
2943 NumberOfBytesRead += NdisBufferLength;
2944 pSrc = (PUCHAR) pVirtualAddress;
2945 Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
2948 // Check DHCP & BOOTP protocol
2950 while (NumberOfBytesRead <= PacketInfo.TotalPacketLength)
2952 if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE))
2954 CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength);
2955 ByteOffset36 = *(pSrc + CurrentOffset);
2956 ReadFirstParm = FALSE;
2959 if (NumberOfBytesRead >= 37)
2961 CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength);
2962 ByteOffset38 = *(pSrc + CurrentOffset);
2969 // Check for DHCP & BOOTP protocol
2970 if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43))
2973 // 2054 (hex 0806) for ARP datagrams
2974 // if this packet is not ARP datagrams, then do nothing
2975 // ARP datagrams will also be duplicate at 1mb broadcast frames
2977 if (Protocol != 0x0806 )
2985 BOOLEAN RTMPCheckEtherType(
2986 IN PRTMP_ADAPTER pAd,
2987 IN PNDIS_PACKET pPacket)
2993 UINT16 srcPort, dstPort;
2994 BOOLEAN status = TRUE;
2997 pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
2998 pktLen = GET_OS_PKT_LEN(pPacket);
3002 RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
3004 // get Ethernet protocol field
3005 TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13];
3007 pSrcBuf += LENGTH_802_3; // Skip the Ethernet Header.
3009 if (TypeLen <= 1500)
3010 { // 802.3, 802.3 LLC
3012 DestMAC(6) + SrcMAC(6) + Lenght(2) +
3013 DSAP(1) + SSAP(1) + Control(1) +
3014 if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
3015 => + SNAP (5, OriginationID(3) + etherType(2))
3017 if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03)
3019 Sniff2BytesFromNdisBuffer(pSrcBuf, 6, &Byte0, &Byte1);
3020 RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
3021 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
3022 pSrcBuf += 8; // Skip this LLC/SNAP header
3026 //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.
3030 // If it's a VLAN packet, get the real Type/Length field.
3031 if (TypeLen == 0x8100)
3033 /* 0x8100 means VLAN packets */
3035 /* Dest. MAC Address (6-bytes) +
3036 Source MAC Address (6-bytes) +
3037 Length/Type = 802.1Q Tag Type (2-byte) +
3038 Tag Control Information (2-bytes) +
3039 Length / Type (2-bytes) +
3040 data payload (0-n bytes) +
3042 Frame Check Sequence (4-bytes) */
3044 RTMP_SET_PACKET_VLAN(pPacket, 1);
3045 Sniff2BytesFromNdisBuffer(pSrcBuf, 2, &Byte0, &Byte1);
3046 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
3048 pSrcBuf += 4; // Skip the VLAN Header.
3055 ASSERT((pktLen > 34));
3056 if (*(pSrcBuf + 9) == 0x11)
3058 ASSERT((pktLen > 34)); // 14 for ethernet header, 20 for IP header
3060 pSrcBuf += 20; // Skip the IP header
3061 srcPort = OS_NTOHS(*((UINT16 *)pSrcBuf));
3062 dstPort = OS_NTOHS(*((UINT16 *)(pSrcBuf +2)));
3064 if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44))
3065 { //It's a BOOTP/DHCP packet
3066 RTMP_SET_PACKET_DHCP(pPacket, 1);
3074 RTMP_SET_PACKET_DHCP(pPacket, 1);
3080 RTMP_SET_PACKET_EAPOL(pPacket, 1);
3094 VOID Update_Rssi_Sample(
3095 IN PRTMP_ADAPTER pAd,
3096 IN RSSI_SAMPLE *pRssi,
3097 IN PRXWI_STRUC pRxWI)
3099 CHAR rssi0 = pRxWI->RSSI0;
3100 CHAR rssi1 = pRxWI->RSSI1;
3101 CHAR rssi2 = pRxWI->RSSI2;
3105 pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0);
3106 pRssi->AvgRssi0X8 = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
3107 pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
3112 pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1);
3113 pRssi->AvgRssi1X8 = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
3114 pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
3119 pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2);
3120 pRssi->AvgRssi2X8 = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
3121 pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
3127 // Normal legacy Rx packet indication
3128 VOID Indicate_Legacy_Packet(
3129 IN PRTMP_ADAPTER pAd,
3131 IN UCHAR FromWhichBSSID)
3133 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
3134 UCHAR Header802_3[LENGTH_802_3];
3136 // 1. get 802.3 Header
3138 // a. pointer pRxBlk->pData to payload
3139 // b. modify pRxBlk->DataSize
3140 #ifdef CONFIG_STA_SUPPORT
3141 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3142 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
3143 #endif // CONFIG_STA_SUPPORT //
3145 if (pRxBlk->DataSize > MAX_RX_PKT_LEN)
3149 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
3154 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
3157 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
3160 // pass this 802.3 packet to upper layer or forward this packet to WM directly
3162 #ifdef CONFIG_STA_SUPPORT
3163 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3164 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
3165 #endif // CONFIG_STA_SUPPORT //
3170 // Normal, AMPDU or AMSDU
3171 VOID CmmRxnonRalinkFrameIndicate(
3172 IN PRTMP_ADAPTER pAd,
3174 IN UCHAR FromWhichBSSID)
3176 #ifdef DOT11_N_SUPPORT
3177 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
3179 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
3182 #endif // DOT11_N_SUPPORT //
3184 #ifdef DOT11_N_SUPPORT
3185 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
3188 Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
3191 #endif // DOT11_N_SUPPORT //
3193 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
3199 VOID CmmRxRalinkFrameIndicate(
3200 IN PRTMP_ADAPTER pAd,
3201 IN MAC_TABLE_ENTRY *pEntry,
3203 IN UCHAR FromWhichBSSID)
3205 UCHAR Header802_3[LENGTH_802_3];
3207 UINT16 Payload1Size, Payload2Size;
3209 PNDIS_PACKET pPacket2 = NULL;
3213 Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8);
3215 if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize))
3217 /* skip two byte MSDU2 len */
3219 pRxBlk->DataSize -= 2;
3224 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
3228 // get 802.3 Header and remove LLC
3229 #ifdef CONFIG_STA_SUPPORT
3230 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3231 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
3232 #endif // CONFIG_STA_SUPPORT //
3235 ASSERT(pRxBlk->pRxPacket);
3237 // Ralink Aggregation frame
3238 pAd->RalinkCounters.OneSecRxAggregationCount ++;
3239 Payload1Size = pRxBlk->DataSize - Msdu2Size;
3240 Payload2Size = Msdu2Size - LENGTH_802_3;
3242 pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
3243 #ifdef CONFIG_STA_SUPPORT
3244 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3245 pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID);
3246 #endif // CONFIG_STA_SUPPORT //
3251 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
3255 // update payload size of 1st packet
3256 pRxBlk->DataSize = Payload1Size;
3257 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
3259 #ifdef CONFIG_STA_SUPPORT
3260 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3261 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID);
3262 #endif // CONFIG_STA_SUPPORT //
3266 #ifdef CONFIG_STA_SUPPORT
3267 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3268 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
3269 #endif // CONFIG_STA_SUPPORT //
3274 #define RESET_FRAGFRAME(_fragFrame) \
3276 _fragFrame.RxSize = 0; \
3277 _fragFrame.Sequence = 0; \
3278 _fragFrame.LastFrag = 0; \
3279 _fragFrame.Flags = 0; \
3283 PNDIS_PACKET RTMPDeFragmentDataFrame(
3284 IN PRTMP_ADAPTER pAd,
3287 PHEADER_802_11 pHeader = pRxBlk->pHeader;
3288 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
3289 UCHAR *pData = pRxBlk->pData;
3290 USHORT DataSize = pRxBlk->DataSize;
3291 PNDIS_PACKET pRetPacket = NULL;
3292 UCHAR *pFragBuffer = NULL;
3293 BOOLEAN bReassDone = FALSE;
3294 UCHAR HeaderRoom = 0;
3299 HeaderRoom = pData - (UCHAR *)pHeader;
3301 // Re-assemble the fragmented packets
3302 if (pHeader->Frag == 0) // Frag. Number is 0 : First frag or only one pkt
3304 // the first pkt of fragment, record it.
3305 if (pHeader->FC.MoreFrag)
3307 ASSERT(pAd->FragFrame.pFragPacket);
3308 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
3309 pAd->FragFrame.RxSize = DataSize + HeaderRoom;
3310 NdisMoveMemory(pFragBuffer, pHeader, pAd->FragFrame.RxSize);
3311 pAd->FragFrame.Sequence = pHeader->Sequence;
3312 pAd->FragFrame.LastFrag = pHeader->Frag; // Should be 0
3313 ASSERT(pAd->FragFrame.LastFrag == 0);
3314 goto done; // end of processing this frame
3317 else //Middle & End of fragment
3319 if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
3320 (pHeader->Frag != (pAd->FragFrame.LastFrag + 1)))
3322 // Fragment is not the same sequence or out of fragment number order
3323 // Reset Fragment control blk
3324 RESET_FRAGFRAME(pAd->FragFrame);
3325 DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n"));
3326 goto done; // give up this frame
3328 else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE)
3330 // Fragment frame is too large, it exeeds the maximum frame size.
3331 // Reset Fragment control blk
3332 RESET_FRAGFRAME(pAd->FragFrame);
3333 DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
3334 goto done; // give up this frame
3338 // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.
3339 // In this case, we will dropt it.
3341 if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H)))
3343 DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag));
3344 goto done; // give up this frame
3347 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
3349 // concatenate this fragment into the re-assembly buffer
3350 NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize);
3351 pAd->FragFrame.RxSize += DataSize;
3352 pAd->FragFrame.LastFrag = pHeader->Frag; // Update fragment number
3355 if (pHeader->FC.MoreFrag == FALSE)
3362 // always release rx fragmented packet
3363 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
3365 // return defragmented packet if packet is reassembled completely
3366 // otherwise return NULL
3369 PNDIS_PACKET pNewFragPacket;
3371 // allocate a new packet buffer for fragment
3372 pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
3376 pRetPacket = pAd->FragFrame.pFragPacket;
3377 pAd->FragFrame.pFragPacket = pNewFragPacket;
3378 pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
3379 pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom;
3380 pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
3381 pRxBlk->pRxPacket = pRetPacket;
3385 RESET_FRAGFRAME(pAd->FragFrame);
3393 VOID Indicate_AMSDU_Packet(
3394 IN PRTMP_ADAPTER pAd,
3396 IN UCHAR FromWhichBSSID)
3400 update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
3401 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
3402 nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize);
3405 VOID Indicate_EAPOL_Packet(
3406 IN PRTMP_ADAPTER pAd,
3408 IN UCHAR FromWhichBSSID)
3410 MAC_TABLE_ENTRY *pEntry = NULL;
3413 #ifdef CONFIG_STA_SUPPORT
3414 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3416 pEntry = &pAd->MacTab.Content[BSSID_WCID];
3417 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
3420 #endif // CONFIG_STA_SUPPORT //
3424 DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
3426 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
3431 #define BCN_TBTT_OFFSET 64 //defer 64 us
3432 VOID ReSyncBeaconTime(
3433 IN PRTMP_ADAPTER pAd)
3439 Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
3441 pAd->TbttTickCount++;
3444 // The updated BeaconInterval Value will affect Beacon Interval after two TBTT
3445 // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
3447 if (Offset == (BCN_TBTT_OFFSET-2))
3449 BCN_TIME_CFG_STRUC csr;
3450 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
3451 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; // ASIC register in units of 1/16 TU = 64us
3452 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
3456 if (Offset == (BCN_TBTT_OFFSET-1))
3458 BCN_TIME_CFG_STRUC csr;
3460 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
3461 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU
3462 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);