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;
123 if ((pAd->MACVersion == 0x28600100) && (!IrqState))
124 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);
187 NDIS_STATUS MiniportMMRequestUnlock(
188 IN PRTMP_ADAPTER pAd,
193 PNDIS_PACKET pPacket;
194 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
201 ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
205 // Reset is in progress, stop immediately
206 if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
207 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)||
208 !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
210 Status = NDIS_STATUS_FAILURE;
214 // Check Free priority queue
215 // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing.
217 if (pAd->MACVersion == 0x28600100)
219 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
220 SW_TX_IDX = pAd->TxRing[QueIdx].TxCpuIdx;
221 pTxD = (PTXD_STRUC) pAd->TxRing[QueIdx].Cell[SW_TX_IDX].AllocVa;
225 FreeNum = GET_MGMTRING_FREENO(pAd);
226 SW_TX_IDX = pAd->MgmtRing.TxCpuIdx;
227 pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[SW_TX_IDX].AllocVa;
231 NdisZeroMemory(&TXWI, TXWI_SIZE);
232 Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&TXWI, TXWI_SIZE, pData, Length);
233 if (Status != NDIS_STATUS_SUCCESS)
235 DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
239 Status = MlmeHardTransmit(pAd, QueIdx, pPacket);
240 if (Status != NDIS_STATUS_SUCCESS)
241 RTMPFreeNdisPacket(pAd, pPacket);
245 pAd->RalinkCounters.MgmtRingFullCount++;
246 DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing\n", QueIdx));
256 NDIS_STATUS MlmeDataHardTransmit(
257 IN PRTMP_ADAPTER pAd,
259 IN PNDIS_PACKET pPacket);
261 #define MAX_DATAMM_RETRY 3
263 ========================================================================
266 API for MLME to transmit management frame to AP (BSS Mode)
267 or station (IBSS Mode)
270 pAd Pointer to our adapter
271 pData Pointer to the outgoing 802.11 frame
272 Length Size of outgoing management frame
280 IRQL = DISPATCH_LEVEL
284 ========================================================================
286 NDIS_STATUS MiniportDataMMRequest(
287 IN PRTMP_ADAPTER pAd,
292 PNDIS_PACKET pPacket;
293 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
297 UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN];
299 ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
302 IrqState = pAd->irq_disabled;
306 // Reset is in progress, stop immediately
307 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
308 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)||
309 !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
311 Status = NDIS_STATUS_FAILURE;
315 // Check Free priority queue
316 // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing.
320 // free Tx(QueIdx) resources
321 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
325 // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870
326 NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE));
327 Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE), pData, Length);
328 if (Status != NDIS_STATUS_SUCCESS)
330 DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
334 //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
335 //pAd->CommonCfg.MlmeRate = RATE_2;
338 Status = MlmeDataHardTransmit(pAd, QueIdx, pPacket);
339 if (Status != NDIS_STATUS_SUCCESS)
340 RTMPFreeNdisPacket(pAd, pPacket);
341 retry = MAX_DATAMM_RETRY;
347 printk("retry %d\n", retry);
348 pAd->RalinkCounters.MgmtRingFullCount++;
350 if (retry >= MAX_DATAMM_RETRY)
352 DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in DataRing, MgmtRingFullCount=%ld!\n",
353 QueIdx, pAd->RalinkCounters.MgmtRingFullCount));
357 } while (retry < MAX_DATAMM_RETRY);
365 ========================================================================
368 Copy frame from waiting queue into relative ring buffer and set
369 appropriate ASIC register to kick hardware transmit function
372 pAd Pointer to our adapter
373 pBuffer Pointer to memory of outgoing frame
374 Length Size of outgoing management frame
382 IRQL = DISPATCH_LEVEL
386 ========================================================================
388 NDIS_STATUS MlmeHardTransmit(
389 IN PRTMP_ADAPTER pAd,
391 IN PNDIS_PACKET pPacket)
393 if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
395 return NDIS_STATUS_FAILURE;
399 if ( pAd->MACVersion == 0x28600100 )
400 return MlmeHardTransmitTxRing(pAd,QueIdx,pPacket);
403 return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
408 NDIS_STATUS MlmeHardTransmitTxRing(
409 IN PRTMP_ADAPTER pAd,
411 IN PNDIS_PACKET pPacket)
413 PACKET_INFO PacketInfo;
417 PHEADER_802_11 pHeader_802_11;
418 BOOLEAN bAckRequired, bInsertTimestamp;
421 ULONG SwIdx = pAd->TxRing[QueIdx].TxCpuIdx;
422 PTXWI_STRUC pFirstTxWI;
424 MAC_TABLE_ENTRY *pMacEntry = NULL;
427 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
429 if (pSrcBufVA == NULL)
431 // The buffer shouldn't be NULL
432 return NDIS_STATUS_FAILURE;
435 // Make sure MGMT ring resource won't be used by other threads
436 //NdisAcquireSpinLock(&pAd->TxRingLock);
438 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
442 //NdisReleaseSpinLock(&pAd->TxRingLock);
443 return NDIS_STATUS_FAILURE;
446 SwIdx = pAd->TxRing[QueIdx].TxCpuIdx;
448 pTxD = (PTXD_STRUC) pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa;
450 if (pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket)
452 printk("MlmeHardTransmit Error\n");
453 return NDIS_STATUS_FAILURE;
456 // outgoing frame always wakeup PHY to prevent frame lost
457 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
458 AsicForceWakeup(pAd, FROM_TX);
460 pFirstTxWI =(PTXWI_STRUC)pSrcBufVA;
462 pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXWI_SIZE);
463 if (pHeader_802_11->Addr1[0] & 0x01)
465 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
469 MlmeRate = pAd->CommonCfg.MlmeRate;
472 if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
473 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
475 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
478 // Verify Mlme rate for a / g bands.
479 if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
483 // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
484 // Snice it's been set to 0 while on MgtMacHeaderInit
485 // By the way this will cause frame to be send on PWR_SAVE failed.
488 // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
490 // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
491 if (pHeader_802_11->FC.Type != BTYPE_DATA)
493 if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_REQ) || !(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
495 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
499 pHeader_802_11->FC.PwrMgmt = pAd->CommonCfg.bAPSDForcePowerSave;
503 bInsertTimestamp = FALSE;
504 if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
506 bAckRequired = FALSE;
508 else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
510 if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
512 bAckRequired = FALSE;
513 pHeader_802_11->Duration = 0;
518 pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
519 if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
521 bInsertTimestamp = TRUE;
525 pHeader_802_11->Sequence = pAd->Sequence++;
526 if (pAd->Sequence > 0xfff)
528 // Before radar detection done, mgmt frame can not be sent but probe req
529 // Because we need to use probe req to trigger driver to send probe req in passive scan
530 if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
531 && (pAd->CommonCfg.bIEEE80211H == 1)
532 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
534 DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
535 return (NDIS_STATUS_FAILURE);
539 // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
540 // should always has only one ohysical buffer, and the whole frame size equals
541 // to the first scatter buffer size
544 // Initialize TX Descriptor
545 // For inter-frame gap, the number is for this frame and next frame
546 // For MLME rate, we will fix as 2Mb to match other vendor's implement
548 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
549 // Only beacon use Nseq=TRUE. So here we use Nseq=FALSE.
550 if (pMacEntry == NULL)
552 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
553 0, RESERVED_WCID, (SrcBufLen - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
557 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
558 bInsertTimestamp, FALSE, bAckRequired, FALSE,
559 0, pMacEntry->Aid, (SrcBufLen - TXWI_SIZE),
560 pMacEntry->MaxHTPhyMode.field.MCS, 0,
561 (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
562 IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
565 pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket = pPacket;
566 pAd->TxRing[QueIdx].Cell[SwIdx].pNextNdisPacket = NULL;
568 SrcBufPA = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE);
571 RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_EDCA);
574 pTxD->SDLen0 = SrcBufLen;
576 pTxD->SDPtr0 = SrcBufPA;
579 pAd->RalinkCounters.KickTxCount++;
580 pAd->RalinkCounters.OneSecTxDoneCount++;
582 // Increase TX_CTX_IDX, but write to register later.
583 INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE);
585 RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx*0x10, pAd->TxRing[QueIdx].TxCpuIdx);
587 return NDIS_STATUS_SUCCESS;
592 NDIS_STATUS MlmeDataHardTransmit(
593 IN PRTMP_ADAPTER pAd,
595 IN PNDIS_PACKET pPacket)
597 if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
600 return NDIS_STATUS_FAILURE;
604 return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
609 NDIS_STATUS MlmeHardTransmitMgmtRing(
610 IN PRTMP_ADAPTER pAd,
612 IN PNDIS_PACKET pPacket)
614 PACKET_INFO PacketInfo;
617 PHEADER_802_11 pHeader_802_11;
618 BOOLEAN bAckRequired, bInsertTimestamp;
620 PTXWI_STRUC pFirstTxWI;
621 MAC_TABLE_ENTRY *pMacEntry = NULL;
623 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
624 RTMP_SEM_LOCK(&pAd->MgmtRingLock);
627 if (pSrcBufVA == NULL)
629 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
630 return NDIS_STATUS_FAILURE;
633 // outgoing frame always wakeup PHY to prevent frame lost
634 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
636 AsicForceWakeup(pAd, FROM_TX);
639 AsicForceWakeup(pAd, TRUE);
642 pFirstTxWI = (PTXWI_STRUC)(pSrcBufVA + TXINFO_SIZE);
643 pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); //TXWI_SIZE);
645 if (pHeader_802_11->Addr1[0] & 0x01)
647 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
651 MlmeRate = pAd->CommonCfg.MlmeRate;
654 // Verify Mlme rate for a / g bands.
655 if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
658 if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
659 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
661 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
665 // Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode.
666 if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED
667 || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED
670 if (pAd->LatchRfRegs.Channel > 14)
671 pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
673 pAd->CommonCfg.MlmeTransmit.field.MODE = 0;
678 // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
679 // Snice it's been set to 0 while on MgtMacHeaderInit
680 // By the way this will cause frame to be send on PWR_SAVE failed.
682 // pHeader_802_11->FC.PwrMgmt = 0; // (pAd->StaCfg.Psm == PWR_SAVE);
684 // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
686 // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
687 if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL))
689 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
690 (pHeader_802_11->FC.SubType == SUBTYPE_ACTION))
691 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
693 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
696 bInsertTimestamp = FALSE;
697 if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
699 //Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue.
700 if ((pAd->OpMode == OPMODE_STA) && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL))
702 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
704 bAckRequired = FALSE;
706 else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
708 if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
710 bAckRequired = FALSE;
711 pHeader_802_11->Duration = 0;
716 pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
717 if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
719 bInsertTimestamp = TRUE;
724 pHeader_802_11->Sequence = pAd->Sequence++;
725 if (pAd->Sequence >0xfff)
728 // Before radar detection done, mgmt frame can not be sent but probe req
729 // Because we need to use probe req to trigger driver to send probe req in passive scan
730 if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
731 && (pAd->CommonCfg.bIEEE80211H == 1)
732 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
734 DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
735 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
736 return (NDIS_STATUS_FAILURE);
740 // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
741 // should always has only one ohysical buffer, and the whole frame size equals
742 // to the first scatter buffer size
745 // Initialize TX Descriptor
746 // For inter-frame gap, the number is for this frame and next frame
747 // For MLME rate, we will fix as 2Mb to match other vendor's implement
749 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
750 if (pMacEntry == NULL)
752 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
753 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
757 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
758 bInsertTimestamp, FALSE, bAckRequired, FALSE,
759 0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE),
760 pMacEntry->MaxHTPhyMode.field.MCS, 0,
761 (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
762 IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
765 // Now do hardware-depened kick out.
766 HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen);
768 // Make sure to release MGMT ring resource
769 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
770 return NDIS_STATUS_SUCCESS;
774 /********************************************************************************
776 New DeQueue Procedures.
778 ********************************************************************************/
780 #define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \
782 if (bIntContext == FALSE) \
783 RTMP_IRQ_LOCK((lock), IrqFlags); \
786 #define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \
788 if (bIntContext == FALSE) \
789 RTMP_IRQ_UNLOCK((lock), IrqFlags); \
793 ========================================================================
794 Tx Path design algorithm:
795 Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal),
796 Specific Packet Type. Following show the classification rule and policy for each kinds of packets.
797 Classification Rule=>
798 Multicast: (*addr1 & 0x01) == 0x01
799 Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc.
800 11N Rate : If peer support HT
801 (1).AMPDU -- If TXBA is negotiated.
802 (2).AMSDU -- If AMSDU is capable for both peer and ourself.
803 *). AMSDU can embedded in a AMPDU, but now we didn't support it.
804 (3).Normal -- Other packets which send as 11n rate.
806 B/G Rate : If peer is b/g only.
807 (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6
808 (2).Normal -- Other packets which send as b/g rate.
810 The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
812 Classified Packet Handle Rule=>
814 No ACK, //pTxBlk->bAckRequired = FALSE;
815 No WMM, //pTxBlk->bWMM = FALSE;
816 No piggyback, //pTxBlk->bPiggyBack = FALSE;
817 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
818 Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use
819 the same policy to handle it.
820 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
823 No piggyback, //pTxBlk->bPiggyBack = FALSE;
835 ========================================================================
837 static UCHAR TxPktClassification(
838 IN RTMP_ADAPTER *pAd,
839 IN PNDIS_PACKET pPacket)
841 UCHAR TxFrameType = TX_UNKOWN_FRAME;
843 MAC_TABLE_ENTRY *pMacEntry = NULL;
844 BOOLEAN bHTRate = FALSE;
846 Wcid = RTMP_GET_PACKET_WCID(pPacket);
847 if (Wcid == MCAST_WCID)
848 { // Handle for RA is Broadcast/Multicast Address.
849 return TX_MCAST_FRAME;
852 // Handle for unicast packets
853 pMacEntry = &pAd->MacTab.Content[Wcid];
854 if (RTMP_GET_PACKET_LOWRATE(pPacket))
855 { // It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame
856 TxFrameType = TX_LEGACY_FRAME;
858 else if (IS_HT_RATE(pMacEntry))
859 { // it's a 11n capable packet
861 // Depends on HTPhyMode to check if the peer support the HTRate transmission.
862 // Currently didn't support A-MSDU embedded in A-MPDU
864 if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE))
865 TxFrameType = TX_LEGACY_FRAME;
866 #ifdef UAPSD_AP_SUPPORT
867 else if (RTMP_GET_PACKET_EOSP(pPacket))
868 TxFrameType = TX_LEGACY_FRAME;
869 #endif // UAPSD_AP_SUPPORT //
870 else if((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0)
871 return TX_AMPDU_FRAME;
872 else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED))
873 return TX_AMSDU_FRAME;
875 TxFrameType = TX_LEGACY_FRAME;
878 { // it's a legacy b/g packet.
879 if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) &&
880 (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) &&
881 (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
882 { // if peer support Ralink Aggregation, we use it.
883 TxFrameType = TX_RALINK_FRAME;
887 TxFrameType = TX_LEGACY_FRAME;
891 // Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU.
892 if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) && (TxFrameType == TX_LEGACY_FRAME))
893 TxFrameType = TX_FRAG_FRAME;
899 BOOLEAN RTMP_FillTxBlkInfo(
900 IN RTMP_ADAPTER *pAd,
903 PACKET_INFO PacketInfo;
904 PNDIS_PACKET pPacket;
905 PMAC_TABLE_ENTRY pMacEntry = NULL;
907 pPacket = pTxBlk->pPacket;
908 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
910 pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket);
911 pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket);
912 pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket);
913 pTxBlk->FrameGap = IFS_HTTXOP; // ASIC determine Frame Gap
915 if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket))
916 TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame);
918 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame);
920 // Default to clear this flag
921 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS);
924 if (pTxBlk->Wcid == MCAST_WCID)
926 pTxBlk->pMacEntry = NULL;
928 #ifdef MCAST_RATE_SPECIFIC
929 PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket);
930 if (((*pDA & 0x01) == 0x01) && (*pDA != 0xff))
931 pTxBlk->pTransmit = &pAd->CommonCfg.MCastPhyMode;
933 #endif // MCAST_RATE_SPECIFIC //
934 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
937 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); // AckRequired = FALSE, when broadcast packet in Adhoc mode.
938 //TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate);
939 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag);
940 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
941 if (RTMP_GET_PACKET_MOREDATA(pPacket))
943 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
949 pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
950 pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode;
952 pMacEntry = pTxBlk->pMacEntry;
955 // For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK.
956 if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK)
957 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
959 TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired);
962 // If support WMM, enable it.
964 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
967 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
968 CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))
970 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM);
973 if (pTxBlk->TxFrameType == TX_LEGACY_FRAME)
975 if ( (RTMP_GET_PACKET_LOWRATE(pPacket)) ||
976 ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1)))
977 { // Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate.
978 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
980 // Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it???
981 if (IS_HT_STA(pTxBlk->pMacEntry) &&
982 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) &&
983 ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)))
985 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
986 TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS);
990 if ( (IS_HT_RATE(pMacEntry) == FALSE) &&
991 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE)))
992 { // Currently piggy-back only support when peer is operate in b/g mode.
993 TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack);
996 if (RTMP_GET_PACKET_MOREDATA(pPacket))
998 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
1000 #ifdef UAPSD_AP_SUPPORT
1001 if (RTMP_GET_PACKET_EOSP(pPacket))
1003 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP);
1005 #endif // UAPSD_AP_SUPPORT //
1007 else if (pTxBlk->TxFrameType == TX_FRAG_FRAME)
1009 TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag);
1012 pMacEntry->DebugTxCount++;
1024 BOOLEAN CanDoAggregateTransmit(
1025 IN RTMP_ADAPTER *pAd,
1026 IN NDIS_PACKET *pPacket,
1030 //printk("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType);
1032 if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
1035 if (RTMP_GET_PACKET_DHCP(pPacket) ||
1036 RTMP_GET_PACKET_EAPOL(pPacket) ||
1037 RTMP_GET_PACKET_WAI(pPacket))
1040 if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) &&
1041 ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100)))
1042 { // For AMSDU, allow the packets with total length < max-amsdu size
1046 if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) &&
1047 (pTxBlk->TxPacketList.Number == 2))
1048 { // For RALINK-Aggregation, allow two frames in one batch.
1052 if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP
1060 ========================================================================
1062 Routine Description:
1063 To do the enqueue operation and extract the first item of waiting
1064 list. If a number of available shared memory segments could meet
1065 the request of extracted item, the extracted item will be fragmented
1066 into shared memory segments.
1069 pAd Pointer to our adapter
1070 pQueue Pointer to Waiting Queue
1075 IRQL = DISPATCH_LEVEL
1079 ========================================================================
1081 VOID RTMPDeQueuePacket(
1082 IN PRTMP_ADAPTER pAd,
1083 IN BOOLEAN bIntContext,
1084 IN UCHAR QIdx, /* BulkOutPipeId */
1085 IN UCHAR Max_Tx_Packets)
1087 PQUEUE_ENTRY pEntry = NULL;
1088 PNDIS_PACKET pPacket;
1089 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
1091 PQUEUE_HEADER pQueue;
1092 ULONG FreeNumber[NUM_OF_TX_RING];
1093 UCHAR QueIdx, sQIdx, eQIdx;
1094 unsigned long IrqFlags = 0;
1095 BOOLEAN hasTxDesc = FALSE;
1101 RtmpDiagStruct *pDiagStruct = &pAd->DiagStruct;
1105 if (QIdx == NUM_OF_TX_RING)
1108 //PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA)
1109 eQIdx = 3; // 4 ACs, start from 0.
1113 sQIdx = eQIdx = QIdx;
1116 for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++)
1120 RT28XX_START_DEQUEUE(pAd, QueIdx, IrqFlags);
1123 firstRound = ((QueIdx == 0) ? TRUE : FALSE);
1124 #endif // DBG_DIAGNOSE //
1128 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |
1129 fRTMP_ADAPTER_RADIO_OFF |
1130 fRTMP_ADAPTER_RESET_IN_PROGRESS |
1131 fRTMP_ADAPTER_HALT_IN_PROGRESS |
1132 fRTMP_ADAPTER_NIC_NOT_EXIST))))
1134 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
1138 if (Count >= Max_Tx_Packets)
1141 DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1142 if (&pAd->TxSwQueue[QueIdx] == NULL)
1145 if (firstRound == TRUE)
1146 pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][0]++;
1147 #endif // DBG_DIAGNOSE //
1148 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1152 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
1155 if (firstRound == TRUE)
1157 UCHAR txDescNumLevel, txSwQNumLevel;
1159 txDescNumLevel = (TX_RING_SIZE - FreeNumber[QueIdx]); // Number of occupied hw desc.
1160 txDescNumLevel = ((txDescNumLevel <=15) ? txDescNumLevel : 15);
1161 pDiagStruct->TxDescCnt[pDiagStruct->ArrayCurIdx][txDescNumLevel]++;
1163 txSwQNumLevel = ((pAd->TxSwQueue[QueIdx].Number <=7) ? pAd->TxSwQueue[QueIdx].Number : 8);
1164 pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][txSwQNumLevel]++;
1168 #endif // DBG_DIAGNOSE //
1170 if (FreeNumber[QueIdx] <= 5)
1172 // free Tx(QueIdx) resources
1173 RTMPFreeTXDUponTxDmaDone(pAd, QueIdx);
1174 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
1177 // probe the Queue Head
1178 pQueue = &pAd->TxSwQueue[QueIdx];
1179 if ((pEntry = pQueue->Head) == NULL)
1181 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1186 NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK));
1187 pTxBlk->QueIdx = QueIdx;
1189 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
1191 // Early check to make sure we have enoguh Tx Resource.
1192 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
1195 pAd->PrivateInfo.TxRingFullCnt++;
1197 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1202 pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
1203 pEntry = RemoveHeadQueue(pQueue);
1204 pTxBlk->TotalFrameNum++;
1205 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
1206 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
1207 pTxBlk->pPacket = pPacket;
1208 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
1210 if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME)
1212 // Enhance SW Aggregation Mechanism
1213 if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType))
1215 InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
1216 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1221 if((pEntry = pQueue->Head) == NULL)
1224 // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation.
1225 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
1226 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
1227 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
1228 if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE))
1231 //Remove the packet from the TxSwQueue and insert into pTxBlk
1232 pEntry = RemoveHeadQueue(pQueue);
1234 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
1235 pTxBlk->TotalFrameNum++;
1236 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
1237 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
1238 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
1241 if (pTxBlk->TxPacketList.Number == 1)
1242 pTxBlk->TxFrameType = TX_LEGACY_FRAME;
1246 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1249 Count += pTxBlk->TxPacketList.Number;
1251 // Do HardTransmit now.
1252 Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
1255 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1256 // static rate also need NICUpdateFifoStaCounters() function.
1257 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
1258 NICUpdateFifoStaCounters(pAd);
1262 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
1266 RTUSBKickBulkOut(pAd);
1274 ========================================================================
1276 Routine Description:
1277 Calculates the duration which is required to transmit out frames
1278 with given size and specified rate.
1281 pAd Pointer to our adapter
1283 Size Frame size in units of byte
1286 Duration number in units of usec
1288 IRQL = PASSIVE_LEVEL
1289 IRQL = DISPATCH_LEVEL
1293 ========================================================================
1295 USHORT RTMPCalcDuration(
1296 IN PRTMP_ADAPTER pAd,
1302 if (Rate < RATE_FIRST_OFDM_RATE) // CCK
1304 if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED))
1305 Duration = 96; // 72+24 preamble+plcp
1307 Duration = 192; // 144+48 preamble+plcp
1309 Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]);
1310 if ((Size << 4) % RateIdTo500Kbps[Rate])
1313 else if (Rate <= RATE_LAST_OFDM_RATE)// OFDM rates
1315 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
1316 Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
1317 if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
1322 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
1325 return (USHORT)Duration;
1330 ========================================================================
1332 Routine Description:
1333 Calculates the duration which is required to transmit out frames
1334 with given size and specified rate.
1337 pTxWI Pointer to head of each MPDU to HW.
1338 Ack Setting for Ack requirement bit
1339 Fragment Setting for Fragment bit
1340 RetryMode Setting for retry mode
1341 Ifs Setting for IFS gap
1342 Rate Setting for transmit rate
1343 Service Setting for service
1345 TxPreamble Short or Long preamble when using CCK rates
1346 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1351 IRQL = PASSIVE_LEVEL
1352 IRQL = DISPATCH_LEVEL
1354 See also : BASmartHardTransmit() !!!
1356 ========================================================================
1359 IN PRTMP_ADAPTER pAd,
1360 IN PTXWI_STRUC pOutTxWI,
1363 IN BOOLEAN InsTimestamp,
1366 IN BOOLEAN NSeq, // HW new a sequence.
1375 IN HTTRANSMIT_SETTING *pTransmit)
1377 PMAC_TABLE_ENTRY pMac = NULL;
1381 if (WCID < MAX_LEN_OF_MAC_TABLE)
1382 pMac = &pAd->MacTab.Content[WCID];
1385 // Always use Long preamble before verifiation short preamble functionality works well.
1386 // Todo: remove the following line if short preamble functionality works
1388 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1389 NdisZeroMemory(&TxWI, TXWI_SIZE);
1394 pTxWI->CFACK = CFACK;
1395 pTxWI->TS= InsTimestamp;
1396 pTxWI->AMPDU = AMPDU;
1398 pTxWI->txop= Txopmode;
1401 // John tune the performace with Intel Client in 20 MHz performance
1402 BASize = pAd->CommonCfg.TxBASize;
1406 pTxWI->BAWinSize = BASize;
1407 pTxWI->ShortGI = pTransmit->field.ShortGI;
1408 pTxWI->STBC = pTransmit->field.STBC;
1410 pTxWI->WirelessCliID = WCID;
1411 pTxWI->MPDUtotalByteCount = Length;
1412 pTxWI->PacketId = PID;
1414 // If CCK or OFDM, BW must be 20
1415 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1417 pTxWI->MCS = pTransmit->field.MCS;
1418 pTxWI->PHYMODE = pTransmit->field.MODE;
1419 pTxWI->CFACK = CfAck;
1423 if (pAd->CommonCfg.bMIMOPSEnable)
1425 if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1427 // Dynamic MIMO Power Save Mode
1430 else if (pMac->MmpsMode == MMPS_STATIC)
1432 // Static MIMO Power Save Mode
1433 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1440 //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;
1441 if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled))
1443 pTxWI->MpduDensity = 7;
1447 pTxWI->MpduDensity = pMac->MpduDensity;
1451 pTxWI->PacketId = pTxWI->MCS;
1452 NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC));
1456 VOID RTMPWriteTxWI_Data(
1457 IN PRTMP_ADAPTER pAd,
1458 IN OUT PTXWI_STRUC pTxWI,
1461 HTTRANSMIT_SETTING *pTransmit;
1462 PMAC_TABLE_ENTRY pMacEntry;
1467 pTransmit = pTxBlk->pTransmit;
1468 pMacEntry = pTxBlk->pMacEntry;
1472 // Always use Long preamble before verifiation short preamble functionality works well.
1473 // Todo: remove the following line if short preamble functionality works
1475 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1476 NdisZeroMemory(pTxWI, TXWI_SIZE);
1478 pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1479 pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1480 pTxWI->txop = pTxBlk->FrameGap;
1482 pTxWI->WirelessCliID = pTxBlk->Wcid;
1484 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1485 pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
1487 // If CCK or OFDM, BW must be 20
1488 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1489 pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
1491 // John tune the performace with Intel Client in 20 MHz performance
1492 BASize = pAd->CommonCfg.TxBASize;
1493 if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry))
1495 UCHAR RABAOriIdx = 0; //The RA's BA Originator table index.
1497 RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
1498 BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1501 pTxWI->TxBF = pTransmit->field.TxBF;
1502 pTxWI->BAWinSize = BASize;
1503 pTxWI->ShortGI = pTransmit->field.ShortGI;
1504 pTxWI->STBC = pTransmit->field.STBC;
1506 pTxWI->MCS = pTransmit->field.MCS;
1507 pTxWI->PHYMODE = pTransmit->field.MODE;
1511 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1513 // Dynamic MIMO Power Save Mode
1516 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1518 // Static MIMO Power Save Mode
1519 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1526 if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled))
1528 pTxWI->MpduDensity = 7;
1532 pTxWI->MpduDensity = pMacEntry->MpduDensity;
1537 if (pTxBlk->QueIdx== 0)
1539 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1540 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1542 #endif // DBG_DIAGNOSE //
1544 // for rate adapation
1545 pTxWI->PacketId = pTxWI->MCS;
1549 VOID RTMPWriteTxWI_Cache(
1550 IN PRTMP_ADAPTER pAd,
1551 IN OUT PTXWI_STRUC pTxWI,
1554 PHTTRANSMIT_SETTING pTransmit;
1555 PMAC_TABLE_ENTRY pMacEntry;
1560 pMacEntry = pTxBlk->pMacEntry;
1561 pTransmit = pTxBlk->pTransmit;
1563 if (pMacEntry->bAutoTxRateSwitch)
1565 pTxWI->txop = IFS_HTTXOP;
1567 // If CCK or OFDM, BW must be 20
1568 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1569 pTxWI->ShortGI = pTransmit->field.ShortGI;
1570 pTxWI->STBC = pTransmit->field.STBC;
1572 pTxWI->MCS = pTransmit->field.MCS;
1573 pTxWI->PHYMODE = pTransmit->field.MODE;
1575 // set PID for TxRateSwitching
1576 pTxWI->PacketId = pTransmit->field.MCS;
1579 pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE);
1582 if (pAd->CommonCfg.bMIMOPSEnable)
1584 // MIMO Power Save Mode
1585 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1587 // Dynamic MIMO Power Save Mode
1590 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1592 // Static MIMO Power Save Mode
1593 if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7))
1602 if (pTxBlk->QueIdx== 0)
1604 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1605 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1607 #endif // DBG_DIAGNOSE //
1609 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1615 ========================================================================
1617 Routine Description:
1618 Calculates the duration which is required to transmit out frames
1619 with given size and specified rate.
1622 pTxD Pointer to transmit descriptor
1623 Ack Setting for Ack requirement bit
1624 Fragment Setting for Fragment bit
1625 RetryMode Setting for retry mode
1626 Ifs Setting for IFS gap
1627 Rate Setting for transmit rate
1628 Service Setting for service
1630 TxPreamble Short or Long preamble when using CCK rates
1631 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1636 IRQL = PASSIVE_LEVEL
1637 IRQL = DISPATCH_LEVEL
1639 ========================================================================
1641 VOID RTMPWriteTxDescriptor(
1642 IN PRTMP_ADAPTER pAd,
1648 // Always use Long preamble before verifiation short preamble functionality works well.
1649 // Todo: remove the following line if short preamble functionality works
1651 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1653 pTxD->WIV = (bWIV) ? 1: 0;
1654 pTxD->QSEL= (QueueSEL);
1655 if (pAd->bGenOneHCCA == TRUE)
1656 pTxD->QSEL= FIFO_HCCA;
1661 // should be called only when -
1662 // 1. MEADIA_CONNECTED
1663 // 2. AGGREGATION_IN_USED
1664 // 3. Fragmentation not in used
1665 // 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible
1666 BOOLEAN TxFrameIsAggregatible(
1667 IN PRTMP_ADAPTER pAd,
1668 IN PUCHAR pPrevAddr1,
1672 // can't aggregate EAPOL (802.1x) frame
1673 if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1676 // can't aggregate multicast/broadcast frame
1677 if (p8023hdr[0] & 0x01)
1680 if (INFRA_ON(pAd)) // must be unicast to AP
1682 else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA
1690 ========================================================================
1692 Routine Description:
1693 Check the MSDU Aggregation policy
1694 1.HT aggregation is A-MSDU
1695 2.legaacy rate aggregation is software aggregation by Ralink.
1703 ========================================================================
1705 BOOLEAN PeerIsAggreOn(
1706 IN PRTMP_ADAPTER pAd,
1708 IN PMAC_TABLE_ENTRY pMacEntry)
1710 ULONG AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
1712 if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags))
1714 if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX)
1719 #ifdef AGGREGATION_SUPPORT
1720 if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
1721 { // legacy Ralink Aggregation support
1724 #endif // AGGREGATION_SUPPORT //
1733 ========================================================================
1735 Routine Description:
1736 Check and fine the packet waiting in SW queue with highest priority
1739 pAd Pointer to our adapter
1742 pQueue Pointer to Waiting Queue
1744 IRQL = DISPATCH_LEVEL
1748 ========================================================================
1750 PQUEUE_HEADER RTMPCheckTxSwQueue(
1751 IN PRTMP_ADAPTER pAd,
1757 Number = pAd->TxSwQueue[QID_AC_BK].Number
1758 + pAd->TxSwQueue[QID_AC_BE].Number
1759 + pAd->TxSwQueue[QID_AC_VI].Number
1760 + pAd->TxSwQueue[QID_AC_VO].Number
1761 + pAd->TxSwQueue[QID_HCCA].Number;
1763 if (pAd->TxSwQueue[QID_AC_VO].Head != NULL)
1765 *pQueIdx = QID_AC_VO;
1766 return (&pAd->TxSwQueue[QID_AC_VO]);
1768 else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL)
1770 *pQueIdx = QID_AC_VI;
1771 return (&pAd->TxSwQueue[QID_AC_VI]);
1773 else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL)
1775 *pQueIdx = QID_AC_BE;
1776 return (&pAd->TxSwQueue[QID_AC_BE]);
1778 else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL)
1780 *pQueIdx = QID_AC_BK;
1781 return (&pAd->TxSwQueue[QID_AC_BK]);
1783 else if (pAd->TxSwQueue[QID_HCCA].Head != NULL)
1785 *pQueIdx = QID_HCCA;
1786 return (&pAd->TxSwQueue[QID_HCCA]);
1789 // No packet pending in Tx Sw queue
1790 *pQueIdx = QID_AC_BK;
1796 BOOLEAN RTMPFreeTXDUponTxDmaDone(
1797 IN PRTMP_ADAPTER pAd,
1800 PRTMP_TX_RING pTxRing;
1802 PNDIS_PACKET pPacket;
1804 TXD_STRUC TxD, *pOriTxD;
1806 BOOLEAN bReschedule = FALSE;
1809 ASSERT(QueIdx < NUM_OF_TX_RING);
1810 pTxRing = &pAd->TxRing[QueIdx];
1812 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF, &pTxRing->TxDmaIdx);
1813 while (pTxRing->TxSwFreeIdx != pTxRing->TxDmaIdx)
1815 // static rate also need NICUpdateFifoStaCounters() function.
1816 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
1817 NICUpdateFifoStaCounters(pAd);
1819 /* Note : If (pAd->ate.bQATxStart == TRUE), we will never reach here. */
1821 pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
1823 NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC));
1828 /*====================================================================*/
1830 pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket;
1833 #ifdef CONFIG_5VT_ENHANCE
1834 if (RTMP_GET_PACKET_5VT(pPacket))
1835 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE);
1837 #endif // CONFIG_5VT_ENHANCE //
1838 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
1839 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1841 //Always assign pNdisPacket as NULL after clear
1842 pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket = NULL;
1844 pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket;
1846 ASSERT(pPacket == NULL);
1849 #ifdef CONFIG_5VT_ENHANCE
1850 if (RTMP_GET_PACKET_5VT(pPacket))
1851 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE);
1853 #endif // CONFIG_5VT_ENHANCE //
1854 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
1855 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1857 //Always assign pNextNdisPacket as NULL after clear
1858 pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL;
1860 /*====================================================================*/
1862 pAd->RalinkCounters.TransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0);
1863 pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++;
1864 INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE);
1865 /* get tx_tdx_idx again */
1866 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &pTxRing->TxDmaIdx);
1868 NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC));
1878 ========================================================================
1880 Routine Description:
1881 Process TX Rings DMA Done interrupt, running in DPC level
1884 Adapter Pointer to our adapter
1889 IRQL = DISPATCH_LEVEL
1891 ========================================================================
1893 BOOLEAN RTMPHandleTxRingDmaDoneInterrupt(
1894 IN PRTMP_ADAPTER pAd,
1895 IN INT_SOURCE_CSR_STRUC TxRingBitmap)
1897 unsigned long IrqFlags;
1898 BOOLEAN bReschedule = FALSE;
1900 // Make sure Tx ring resource won't be used by other threads
1902 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1904 if (TxRingBitmap.field.Ac0DmaDone)
1905 bReschedule = RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BE);
1907 if (TxRingBitmap.field.HccaDmaDone)
1908 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_HCCA);
1910 if (TxRingBitmap.field.Ac3DmaDone)
1911 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VO);
1913 if (TxRingBitmap.field.Ac2DmaDone)
1914 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VI);
1916 if (TxRingBitmap.field.Ac1DmaDone)
1917 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BK);
1919 // Make sure to release Tx ring resource
1920 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1922 // Dequeue outgoing frames from TxSwQueue[] and process it
1923 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1930 ========================================================================
1932 Routine Description:
1933 Process MGMT ring DMA done interrupt, running in DPC level
1936 pAd Pointer to our adapter
1941 IRQL = DISPATCH_LEVEL
1945 ========================================================================
1947 VOID RTMPHandleMgmtRingDmaDoneInterrupt(
1948 IN PRTMP_ADAPTER pAd)
1951 PNDIS_PACKET pPacket;
1953 PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing;
1955 NdisAcquireSpinLock(&pAd->MgmtRingLock);
1957 RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pMgmtRing->TxDmaIdx);
1958 while (pMgmtRing->TxSwFreeIdx!= pMgmtRing->TxDmaIdx)
1961 pTxD = (PTXD_STRUC) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa);
1963 pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket;
1968 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
1969 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1971 pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket = NULL;
1973 pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket;
1976 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
1977 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1979 pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket = NULL;
1980 INC_RING_INDEX(pMgmtRing->TxSwFreeIdx, MGMT_RING_SIZE);
1982 NdisReleaseSpinLock(&pAd->MgmtRingLock);
1988 ========================================================================
1990 Routine Description:
1992 Adapter Pointer to our adapter. Dequeue all power safe delayed braodcast frames after beacon.
1994 IRQL = DISPATCH_LEVEL
1996 ========================================================================
1998 VOID RTMPHandleTBTTInterrupt(
1999 IN PRTMP_ADAPTER pAd)
2002 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2010 ========================================================================
2012 Routine Description:
2014 Adapter Pointer to our adapter. Rewrite beacon content before next send-out.
2016 IRQL = DISPATCH_LEVEL
2018 ========================================================================
2020 VOID RTMPHandlePreTBTTInterrupt(
2021 IN PRTMP_ADAPTER pAd)
2024 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2026 DBGPRINT(RT_DEBUG_TRACE, ("RTMPHandlePreTBTTInterrupt...\n"));
2033 VOID RTMPHandleRxCoherentInterrupt(
2034 IN PRTMP_ADAPTER pAd)
2036 WPDMA_GLO_CFG_STRUC GloCfg;
2040 DBGPRINT(RT_DEBUG_TRACE, ("====> pAd is NULL, return.\n"));
2044 DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPHandleRxCoherentInterrupt \n"));
2046 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG , &GloCfg.word);
2048 GloCfg.field.EnTXWriteBackDDONE = 0;
2049 GloCfg.field.EnableRxDMA = 0;
2050 GloCfg.field.EnableTxDMA = 0;
2051 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
2053 RTMPRingCleanUp(pAd, QID_AC_BE);
2054 RTMPRingCleanUp(pAd, QID_AC_BK);
2055 RTMPRingCleanUp(pAd, QID_AC_VI);
2056 RTMPRingCleanUp(pAd, QID_AC_VO);
2057 RTMPRingCleanUp(pAd, QID_HCCA);
2058 RTMPRingCleanUp(pAd, QID_MGMT);
2059 RTMPRingCleanUp(pAd, QID_RX);
2061 RTMPEnableRxTx(pAd);
2063 DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPHandleRxCoherentInterrupt \n"));
2067 VOID DBGPRINT_TX_RING(
2068 IN PRTMP_ADAPTER pAd,
2072 UINT32 Ac0HwIdx = 0, Ac0SwIdx = 0, AC0freeIdx;
2076 DBGPRINT_RAW(RT_DEBUG_TRACE, ("=====================================================\n " ));
2080 RTMP_IO_READ32(pAd, TX_BASE_PTR0, &Ac0Base);
2081 RTMP_IO_READ32(pAd, TX_CTX_IDX0, &Ac0SwIdx);
2082 RTMP_IO_READ32(pAd, TX_DTX_IDX0, &Ac0HwIdx);
2083 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_BE DESCRIPTOR \n " ));
2084 for (i=0;i<TX_RING_SIZE;i++)
2086 ptemp= (PULONG)pAd->TxRing[QID_AC_BE].Cell[i].AllocVa;
2087 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
2089 DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
2092 RTMP_IO_READ32(pAd, TX_BASE_PTR1, &Ac0Base);
2093 RTMP_IO_READ32(pAd, TX_CTX_IDX1, &Ac0SwIdx);
2094 RTMP_IO_READ32(pAd, TX_DTX_IDX1, &Ac0HwIdx);
2095 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_BK DESCRIPTOR \n " ));
2096 for (i=0;i<TX_RING_SIZE;i++)
2098 ptemp= (PULONG)pAd->TxRing[QID_AC_BK].Cell[i].AllocVa;
2099 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
2101 DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
2104 RTMP_IO_READ32(pAd, TX_BASE_PTR2, &Ac0Base);
2105 RTMP_IO_READ32(pAd, TX_CTX_IDX2, &Ac0SwIdx);
2106 RTMP_IO_READ32(pAd, TX_DTX_IDX2, &Ac0HwIdx);
2107 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_VI DESCRIPTOR \n " ));
2108 for (i=0;i<TX_RING_SIZE;i++)
2110 ptemp= (PULONG)pAd->TxRing[QID_AC_VI].Cell[i].AllocVa;
2111 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
2113 DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
2116 RTMP_IO_READ32(pAd, TX_BASE_PTR3, &Ac0Base);
2117 RTMP_IO_READ32(pAd, TX_CTX_IDX3, &Ac0SwIdx);
2118 RTMP_IO_READ32(pAd, TX_DTX_IDX3, &Ac0HwIdx);
2119 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_VO DESCRIPTOR \n " ));
2120 for (i=0;i<TX_RING_SIZE;i++)
2122 ptemp= (PULONG)pAd->TxRing[QID_AC_VO].Cell[i].AllocVa;
2123 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
2125 DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
2128 RTMP_IO_READ32(pAd, TX_BASE_PTR5, &Ac0Base);
2129 RTMP_IO_READ32(pAd, TX_CTX_IDX5, &Ac0SwIdx);
2130 RTMP_IO_READ32(pAd, TX_DTX_IDX5, &Ac0HwIdx);
2131 DBGPRINT_RAW(RT_DEBUG_TRACE, (" All QID_MGMT DESCRIPTOR \n " ));
2132 for (i=0;i<MGMT_RING_SIZE;i++)
2134 ptemp= (PULONG)pAd->MgmtRing.Cell[i].AllocVa;
2135 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
2137 DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
2141 DBGPRINT_ERR(("DBGPRINT_TX_RING(Ring %d) not supported\n", QueIdx));
2144 AC0freeIdx = pAd->TxRing[QueIdx].TxSwFreeIdx;
2146 DBGPRINT(RT_DEBUG_TRACE,("TxRing%d, TX_DTX_IDX=%d, TX_CTX_IDX=%d\n", QueIdx, Ac0HwIdx, Ac0SwIdx));
2147 DBGPRINT_RAW(RT_DEBUG_TRACE,(" TxSwFreeIdx[%d]", AC0freeIdx));
2148 DBGPRINT_RAW(RT_DEBUG_TRACE,(" pending-NDIS=%ld\n", pAd->RalinkCounters.PendingNdisPacketCount));
2154 VOID DBGPRINT_RX_RING(
2155 IN PRTMP_ADAPTER pAd)
2158 UINT32 Ac0HwIdx = 0, Ac0SwIdx = 0, AC0freeIdx;
2162 DBGPRINT_RAW(RT_DEBUG_TRACE, ("=====================================================\n " ));
2163 RTMP_IO_READ32(pAd, RX_BASE_PTR, &Ac0Base);
2164 RTMP_IO_READ32(pAd, RX_CRX_IDX, &Ac0SwIdx);
2165 RTMP_IO_READ32(pAd, RX_DRX_IDX, &Ac0HwIdx);
2166 AC0freeIdx = pAd->RxRing.RxSwReadIdx;
2168 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All RX DSP \n " ));
2169 for (i=0;i<RX_RING_SIZE;i++)
2171 ptemp = (UINT32 *)pAd->RxRing.Cell[i].AllocVa;
2172 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08x: %08x: %08x: %08x\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
2174 DBGPRINT(RT_DEBUG_TRACE,("RxRing, RX_DRX_IDX=%d, RX_CRX_IDX=%d \n", Ac0HwIdx, Ac0SwIdx));
2175 DBGPRINT_RAW(RT_DEBUG_TRACE,(" RxSwReadIdx [%d]=", AC0freeIdx));
2176 DBGPRINT_RAW(RT_DEBUG_TRACE,(" pending-NDIS=%ld\n", pAd->RalinkCounters.PendingNdisPacketCount));
2181 ========================================================================
2183 Routine Description:
2184 Suspend MSDU transmission
2187 pAd Pointer to our adapter
2194 ========================================================================
2196 VOID RTMPSuspendMsduTransmission(
2197 IN PRTMP_ADAPTER pAd)
2199 DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n"));
2203 // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
2204 // use Lowbound as R66 value on ScanNextChannel(...)
2206 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue);
2208 // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)
2209 RTMPSetAGCInitValue(pAd, BW_20);
2211 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
2216 ========================================================================
2218 Routine Description:
2219 Resume MSDU transmission
2222 pAd Pointer to our adapter
2227 IRQL = DISPATCH_LEVEL
2231 ========================================================================
2233 VOID RTMPResumeMsduTransmission(
2234 IN PRTMP_ADAPTER pAd)
2236 DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
2239 // After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value
2240 // R66 should not be 0
2241 if (pAd->BbpTuning.R66CurrentValue == 0)
2243 pAd->BbpTuning.R66CurrentValue = 0x38;
2244 DBGPRINT_ERR(("RTMPResumeMsduTransmission, R66CurrentValue=0...\n"));
2247 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue);
2249 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
2250 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
2254 UINT deaggregate_AMSDU_announce(
2255 IN PRTMP_ADAPTER pAd,
2256 PNDIS_PACKET pPacket,
2261 USHORT SubFrameSize;
2262 PHEADER_802_3 pAMSDUsubheader;
2264 UCHAR Header802_3[14];
2266 PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP;
2267 PNDIS_PACKET pClonePacket;
2273 while (DataSize > LENGTH_802_3)
2278 pAMSDUsubheader = (PHEADER_802_3)pData;
2279 PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8);
2280 SubFrameSize = PayloadSize + LENGTH_802_3;
2283 if ((DataSize < SubFrameSize) || (PayloadSize > 1518 ))
2288 pPayload = pData + LENGTH_802_3;
2290 pSA = pData + MAC_ADDR_LEN;
2292 // convert to 802.3 header
2293 CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP);
2295 if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) )
2297 // avoid local heap overflow, use dyanamic allocation
2298 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
2299 memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize);
2300 Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize;
2301 WpaEAPOLKeyAction(pAd, Elem);
2306 if (pRemovedLLCSNAP)
2308 pPayload -= LENGTH_802_3;
2309 PayloadSize += LENGTH_802_3;
2310 NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3);
2314 pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
2317 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket));
2321 // A-MSDU has padding to multiple of 4 including subframe header.
2322 // align SubFrameSize up to multiple of 4
2323 SubFrameSize = (SubFrameSize+3)&(~0x3);
2326 if (SubFrameSize > 1528 || SubFrameSize < 32)
2331 if (DataSize > SubFrameSize)
2333 pData += SubFrameSize;
2334 DataSize -= SubFrameSize;
2343 // finally release original rx packet
2344 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
2350 UINT BA_Reorder_AMSDU_Annnounce(
2351 IN PRTMP_ADAPTER pAd,
2352 IN PNDIS_PACKET pPacket)
2358 pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
2359 DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
2361 nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
2368 ==========================================================================
2370 Look up the MAC address in the MAC table. Return NULL if not found.
2372 pEntry - pointer to the MAC entry; NULL is not found
2373 ==========================================================================
2375 MAC_TABLE_ENTRY *MacTableLookup(
2376 IN PRTMP_ADAPTER pAd,
2380 MAC_TABLE_ENTRY *pEntry = NULL;
2382 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
2383 pEntry = pAd->MacTab.Hash[HashIdx];
2385 while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh))
2387 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
2392 pEntry = pEntry->pNext;
2398 MAC_TABLE_ENTRY *MacTableInsertEntry(
2399 IN PRTMP_ADAPTER pAd,
2402 IN BOOLEAN CleanAll)
2406 MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
2409 if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
2414 if (pAd->StaCfg.BssType == BSS_INFRA)
2417 // allocate one MAC entry
2418 NdisAcquireSpinLock(&pAd->MacTabLock);
2419 for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++) // skip entry#0 so that "entry index == AID" for fast lookup
2421 // pick up the first available vacancy
2422 if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
2423 (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
2424 (pAd->MacTab.Content[i].ValidAsApCli== FALSE) &&
2425 (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
2428 pEntry = &pAd->MacTab.Content[i];
2429 if (CleanAll == TRUE)
2431 pEntry->MaxSupportedRate = RATE_11;
2432 pEntry->CurrTxRate = RATE_11;
2433 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
2434 pEntry->PairwiseKey.KeyLen = 0;
2435 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
2439 pEntry->ValidAsCLI = TRUE;
2440 pEntry->ValidAsWDS = FALSE;
2441 pEntry->ValidAsApCli = FALSE;
2442 pEntry->ValidAsMesh = FALSE;
2443 pEntry->ValidAsDls = FALSE;
2447 pEntry->bIAmBadAtheros = FALSE;
2449 pEntry->CMTimerRunning = FALSE;
2450 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
2451 pEntry->RSNIE_Len = 0;
2452 NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
2453 pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
2455 if (pEntry->ValidAsMesh)
2456 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH);
2457 else if (pEntry->ValidAsApCli)
2458 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI);
2459 else if (pEntry->ValidAsWDS)
2460 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS);
2462 pEntry->apidx = apidx;
2466 pEntry->AuthMode = pAd->StaCfg.AuthMode;
2467 pEntry->WepStatus = pAd->StaCfg.WepStatus;
2468 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
2470 AsicRemovePairwiseKeyEntry(pAd, pEntry->apidx, (UCHAR)i);
2475 pEntry->GTKState = REKEY_NEGOTIATING;
2476 pEntry->PairwiseKey.KeyLen = 0;
2477 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
2480 if ((pAd->OpMode == OPMODE_STA) &&
2481 (pAd->StaCfg.BssType == BSS_ADHOC))
2482 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
2485 pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
2487 pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
2488 COPY_MAC_ADDR(pEntry->Addr, pAddr);
2489 pEntry->Sst = SST_NOT_AUTH;
2490 pEntry->AuthState = AS_NOT_AUTH;
2491 pEntry->Aid = (USHORT)i; //0;
2492 pEntry->CapabilityInfo = 0;
2493 pEntry->PsMode = PWR_ACTIVE;
2494 pEntry->PsQIdleCount = 0;
2495 pEntry->NoDataIdleCount = 0;
2496 pEntry->ContinueTxFailCnt = 0;
2497 InitializeQueueHeader(&pEntry->PsQueue);
2500 pAd->MacTab.Size ++;
2501 // Add this entry into ASIC RX WCID search table
2502 RT28XX_STA_ENTRY_ADD(pAd, pEntry);
2506 DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size));
2511 // add this MAC entry into HASH table
2514 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
2515 if (pAd->MacTab.Hash[HashIdx] == NULL)
2517 pAd->MacTab.Hash[HashIdx] = pEntry;
2521 pCurrEntry = pAd->MacTab.Hash[HashIdx];
2522 while (pCurrEntry->pNext != NULL)
2523 pCurrEntry = pCurrEntry->pNext;
2524 pCurrEntry->pNext = pEntry;
2528 NdisReleaseSpinLock(&pAd->MacTabLock);
2533 ==========================================================================
2535 Delete a specified client from MAC table
2536 ==========================================================================
2538 BOOLEAN MacTableDeleteEntry(
2539 IN PRTMP_ADAPTER pAd,
2544 MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
2547 if (wcid >= MAX_LEN_OF_MAC_TABLE)
2550 NdisAcquireSpinLock(&pAd->MacTabLock);
2552 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
2553 pEntry = &pAd->MacTab.Content[wcid];
2555 if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh
2558 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
2561 // Delete this entry from ASIC on-chip WCID Table
2562 RT28XX_STA_ENTRY_MAC_RESET(pAd, wcid);
2564 // free resources of BA
2565 BASessionTearDownALL(pAd, pEntry->Aid);
2568 pProbeEntry = pAd->MacTab.Hash[HashIdx];
2569 ASSERT(pProbeEntry);
2574 if (pProbeEntry == pEntry)
2576 if (pPrevEntry == NULL)
2578 pAd->MacTab.Hash[HashIdx] = pEntry->pNext;
2582 pPrevEntry->pNext = pEntry->pNext;
2587 pPrevEntry = pProbeEntry;
2588 pProbeEntry = pProbeEntry->pNext;
2589 } while (pProbeEntry);
2592 ASSERT(pProbeEntry != NULL);
2594 RT28XX_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
2597 if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
2599 RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
2600 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
2604 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
2605 pAd->MacTab.Size --;
2606 DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size));
2610 printk("\n%s: Impossible Wcid = %d !!!!!\n", __func__, wcid);
2614 NdisReleaseSpinLock(&pAd->MacTabLock);
2616 //Reset operating mode when no Sta.
2617 if (pAd->MacTab.Size == 0)
2619 pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
2621 AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/);
2624 RT28XX_UPDATE_PROTECT(pAd); // edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet
2633 ==========================================================================
2635 This routine reset the entire MAC table. All packets pending in
2636 the power-saving queues are freed here.
2637 ==========================================================================
2640 IN PRTMP_ADAPTER pAd)
2644 DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
2645 //NdisAcquireSpinLock(&pAd->MacTabLock);
2647 for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
2650 RT28XX_STA_ENTRY_MAC_RESET(pAd, i);
2652 if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
2654 // free resources of BA
2655 BASessionTearDownALL(pAd, i);
2657 pAd->MacTab.Content[i].ValidAsCLI = FALSE;
2662 NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6);
2663 RT28XX_STA_ENTRY_MAC_RESET(pAd, i);
2666 //AsicDelWcidTab(pAd, i);
2674 ==========================================================================
2677 IRQL = DISPATCH_LEVEL
2679 ==========================================================================
2682 IN PRTMP_ADAPTER pAd,
2683 IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
2685 IN USHORT CapabilityInfo,
2687 IN USHORT ListenIntv)
2689 COPY_MAC_ADDR(AssocReq->Addr, pAddr);
2690 // Add mask to support 802.11b mode only
2691 AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request
2692 AssocReq->Timeout = Timeout;
2693 AssocReq->ListenIntv = ListenIntv;
2698 ==========================================================================
2701 IRQL = DISPATCH_LEVEL
2703 ==========================================================================
2705 VOID DisassocParmFill(
2706 IN PRTMP_ADAPTER pAd,
2707 IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
2711 COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
2712 DisassocReq->Reason = Reason;
2717 ========================================================================
2719 Routine Description:
2720 Check the out going frame, if this is an DHCP or ARP datagram
2721 will be duplicate another frame at low data rate transmit.
2724 pAd Pointer to our adapter
2725 pPacket Pointer to outgoing Ndis frame
2728 TRUE To be duplicate at Low data rate transmit. (1mb)
2731 IRQL = DISPATCH_LEVEL
2735 MAC header + IP Header + UDP Header
2739 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
2741 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
2744 port 0x43 means Bootstrap Protocol, server.
2745 Port 0x44 means Bootstrap Protocol, client.
2747 ========================================================================
2750 BOOLEAN RTMPCheckDHCPFrame(
2751 IN PRTMP_ADAPTER pAd,
2752 IN PNDIS_PACKET pPacket)
2754 PACKET_INFO PacketInfo;
2755 ULONG NumberOfBytesRead = 0;
2756 ULONG CurrentOffset = 0;
2757 PVOID pVirtualAddress = NULL;
2758 UINT NdisBufferLength;
2761 UCHAR ByteOffset36 = 0;
2762 UCHAR ByteOffset38 = 0;
2763 BOOLEAN ReadFirstParm = TRUE;
2765 RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength);
2767 NumberOfBytesRead += NdisBufferLength;
2768 pSrc = (PUCHAR) pVirtualAddress;
2769 Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
2772 // Check DHCP & BOOTP protocol
2774 while (NumberOfBytesRead <= PacketInfo.TotalPacketLength)
2776 if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE))
2778 CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength);
2779 ByteOffset36 = *(pSrc + CurrentOffset);
2780 ReadFirstParm = FALSE;
2783 if (NumberOfBytesRead >= 37)
2785 CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength);
2786 ByteOffset38 = *(pSrc + CurrentOffset);
2793 // Check for DHCP & BOOTP protocol
2794 if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43))
2797 // 2054 (hex 0806) for ARP datagrams
2798 // if this packet is not ARP datagrams, then do nothing
2799 // ARP datagrams will also be duplicate at 1mb broadcast frames
2801 if (Protocol != 0x0806 )
2809 BOOLEAN RTMPCheckEtherType(
2810 IN PRTMP_ADAPTER pAd,
2811 IN PNDIS_PACKET pPacket)
2817 UINT16 srcPort, dstPort;
2818 BOOLEAN status = TRUE;
2821 pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
2822 pktLen = GET_OS_PKT_LEN(pPacket);
2826 RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
2828 // get Ethernet protocol field
2829 TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13];
2831 pSrcBuf += LENGTH_802_3; // Skip the Ethernet Header.
2833 if (TypeLen <= 1500)
2834 { // 802.3, 802.3 LLC
2836 DestMAC(6) + SrcMAC(6) + Lenght(2) +
2837 DSAP(1) + SSAP(1) + Control(1) +
2838 if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
2839 => + SNAP (5, OriginationID(3) + etherType(2))
2841 if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03)
2843 Sniff2BytesFromNdisBuffer(pSrcBuf, 6, &Byte0, &Byte1);
2844 RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
2845 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2846 pSrcBuf += 8; // Skip this LLC/SNAP header
2850 //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.
2854 // If it's a VLAN packet, get the real Type/Length field.
2855 if (TypeLen == 0x8100)
2857 /* 0x8100 means VLAN packets */
2859 /* Dest. MAC Address (6-bytes) +
2860 Source MAC Address (6-bytes) +
2861 Length/Type = 802.1Q Tag Type (2-byte) +
2862 Tag Control Information (2-bytes) +
2863 Length / Type (2-bytes) +
2864 data payload (0-n bytes) +
2866 Frame Check Sequence (4-bytes) */
2868 RTMP_SET_PACKET_VLAN(pPacket, 1);
2869 Sniff2BytesFromNdisBuffer(pSrcBuf, 2, &Byte0, &Byte1);
2870 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2872 pSrcBuf += 4; // Skip the VLAN Header.
2879 ASSERT((pktLen > 34));
2880 if (*(pSrcBuf + 9) == 0x11)
2882 ASSERT((pktLen > 34)); // 14 for ethernet header, 20 for IP header
2884 pSrcBuf += 20; // Skip the IP header
2885 srcPort = OS_NTOHS(*((UINT16 *)pSrcBuf));
2886 dstPort = OS_NTOHS(*((UINT16 *)(pSrcBuf +2)));
2888 if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44))
2889 { //It's a BOOTP/DHCP packet
2890 RTMP_SET_PACKET_DHCP(pPacket, 1);
2898 RTMP_SET_PACKET_DHCP(pPacket, 1);
2904 RTMP_SET_PACKET_EAPOL(pPacket, 1);
2918 VOID Update_Rssi_Sample(
2919 IN PRTMP_ADAPTER pAd,
2920 IN RSSI_SAMPLE *pRssi,
2921 IN PRXWI_STRUC pRxWI)
2923 CHAR rssi0 = pRxWI->RSSI0;
2924 CHAR rssi1 = pRxWI->RSSI1;
2925 CHAR rssi2 = pRxWI->RSSI2;
2929 pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0);
2930 pRssi->AvgRssi0X8 = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
2931 pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
2936 pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1);
2937 pRssi->AvgRssi1X8 = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
2938 pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
2943 pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2);
2944 pRssi->AvgRssi2X8 = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
2945 pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
2951 // Normal legacy Rx packet indication
2952 VOID Indicate_Legacy_Packet(
2953 IN PRTMP_ADAPTER pAd,
2955 IN UCHAR FromWhichBSSID)
2957 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2958 UCHAR Header802_3[LENGTH_802_3];
2960 // 1. get 802.3 Header
2962 // a. pointer pRxBlk->pData to payload
2963 // b. modify pRxBlk->DataSize
2964 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2966 if (pRxBlk->DataSize > MAX_RX_PKT_LEN)
2970 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2975 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
2978 if (pAd->CommonCfg.bDisableReordering == 0)
2980 PBA_REC_ENTRY pBAEntry;
2982 UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID;
2983 UCHAR TID = pRxBlk->pRxWI->TID;
2986 #define REORDERING_PACKET_TIMEOUT ((100 * HZ)/1000) // system ticks -- 100 ms
2988 if (Wcid < MAX_LEN_OF_MAC_TABLE)
2990 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
2993 pBAEntry = &pAd->BATable.BARecEntry[Idx];
2994 // update last rx time
2995 NdisGetSystemUpTime(&Now32);
2996 if ((pBAEntry->list.qlen > 0) &&
2997 RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
3000 printk("Indicate_Legacy_Packet():flush reordering_timeout_mpdus! RxWI->Flags=%d, pRxWI.TID=%d, RxD->AMPDU=%d!\n", pRxBlk->Flags, pRxBlk->pRxWI->TID, pRxBlk->RxD.AMPDU);
3001 hex_dump("Dump the legacy Packet:", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), 64);
3002 ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
3009 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
3012 // pass this 802.3 packet to upper layer or forward this packet to WM directly
3014 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
3018 // Normal, AMPDU or AMSDU
3019 VOID CmmRxnonRalinkFrameIndicate(
3020 IN PRTMP_ADAPTER pAd,
3022 IN UCHAR FromWhichBSSID)
3024 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
3026 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
3030 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
3033 Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
3037 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
3043 VOID CmmRxRalinkFrameIndicate(
3044 IN PRTMP_ADAPTER pAd,
3045 IN MAC_TABLE_ENTRY *pEntry,
3047 IN UCHAR FromWhichBSSID)
3049 UCHAR Header802_3[LENGTH_802_3];
3051 UINT16 Payload1Size, Payload2Size;
3053 PNDIS_PACKET pPacket2 = NULL;
3057 Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8);
3059 if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize))
3061 /* skip two byte MSDU2 len */
3063 pRxBlk->DataSize -= 2;
3068 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
3072 // get 802.3 Header and remove LLC
3073 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
3075 ASSERT(pRxBlk->pRxPacket);
3077 // Ralink Aggregation frame
3078 pAd->RalinkCounters.OneSecRxAggregationCount ++;
3079 Payload1Size = pRxBlk->DataSize - Msdu2Size;
3080 Payload2Size = Msdu2Size - LENGTH_802_3;
3082 pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
3084 pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID);
3089 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
3093 // update payload size of 1st packet
3094 pRxBlk->DataSize = Payload1Size;
3095 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
3097 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID);
3101 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
3106 #define RESET_FRAGFRAME(_fragFrame) \
3108 _fragFrame.RxSize = 0; \
3109 _fragFrame.Sequence = 0; \
3110 _fragFrame.LastFrag = 0; \
3111 _fragFrame.Flags = 0; \
3115 PNDIS_PACKET RTMPDeFragmentDataFrame(
3116 IN PRTMP_ADAPTER pAd,
3119 PHEADER_802_11 pHeader = pRxBlk->pHeader;
3120 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
3121 UCHAR *pData = pRxBlk->pData;
3122 USHORT DataSize = pRxBlk->DataSize;
3123 PNDIS_PACKET pRetPacket = NULL;
3124 UCHAR *pFragBuffer = NULL;
3125 BOOLEAN bReassDone = FALSE;
3126 UCHAR HeaderRoom = 0;
3131 HeaderRoom = pData - (UCHAR *)pHeader;
3133 // Re-assemble the fragmented packets
3134 if (pHeader->Frag == 0) // Frag. Number is 0 : First frag or only one pkt
3136 // the first pkt of fragment, record it.
3137 if (pHeader->FC.MoreFrag)
3139 ASSERT(pAd->FragFrame.pFragPacket);
3140 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
3141 pAd->FragFrame.RxSize = DataSize + HeaderRoom;
3142 NdisMoveMemory(pFragBuffer, pHeader, pAd->FragFrame.RxSize);
3143 pAd->FragFrame.Sequence = pHeader->Sequence;
3144 pAd->FragFrame.LastFrag = pHeader->Frag; // Should be 0
3145 ASSERT(pAd->FragFrame.LastFrag == 0);
3146 goto done; // end of processing this frame
3149 else //Middle & End of fragment
3151 if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
3152 (pHeader->Frag != (pAd->FragFrame.LastFrag + 1)))
3154 // Fragment is not the same sequence or out of fragment number order
3155 // Reset Fragment control blk
3156 RESET_FRAGFRAME(pAd->FragFrame);
3157 DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n"));
3158 goto done; // give up this frame
3160 else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE)
3162 // Fragment frame is too large, it exeeds the maximum frame size.
3163 // Reset Fragment control blk
3164 RESET_FRAGFRAME(pAd->FragFrame);
3165 DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
3166 goto done; // give up this frame
3170 // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.
3171 // In this case, we will dropt it.
3173 if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H)))
3175 DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag));
3176 goto done; // give up this frame
3179 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
3181 // concatenate this fragment into the re-assembly buffer
3182 NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize);
3183 pAd->FragFrame.RxSize += DataSize;
3184 pAd->FragFrame.LastFrag = pHeader->Frag; // Update fragment number
3187 if (pHeader->FC.MoreFrag == FALSE)
3194 // always release rx fragmented packet
3195 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
3197 // return defragmented packet if packet is reassembled completely
3198 // otherwise return NULL
3201 PNDIS_PACKET pNewFragPacket;
3203 // allocate a new packet buffer for fragment
3204 pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
3208 pRetPacket = pAd->FragFrame.pFragPacket;
3209 pAd->FragFrame.pFragPacket = pNewFragPacket;
3210 pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
3211 pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom;
3212 pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
3213 pRxBlk->pRxPacket = pRetPacket;
3217 RESET_FRAGFRAME(pAd->FragFrame);
3225 VOID Indicate_AMSDU_Packet(
3226 IN PRTMP_ADAPTER pAd,
3228 IN UCHAR FromWhichBSSID)
3232 update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
3233 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
3234 nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize);
3237 VOID Indicate_EAPOL_Packet(
3238 IN PRTMP_ADAPTER pAd,
3240 IN UCHAR FromWhichBSSID)
3242 MAC_TABLE_ENTRY *pEntry = NULL;
3245 pEntry = &pAd->MacTab.Content[BSSID_WCID];
3246 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
3252 DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
3254 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
3259 #define BCN_TBTT_OFFSET 64 //defer 64 us
3260 VOID ReSyncBeaconTime(
3261 IN PRTMP_ADAPTER pAd)
3267 Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
3269 pAd->TbttTickCount++;
3272 // The updated BeaconInterval Value will affect Beacon Interval after two TBTT
3273 // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
3275 if (Offset == (BCN_TBTT_OFFSET-2))
3277 BCN_TIME_CFG_STRUC csr;
3278 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
3279 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; // ASIC register in units of 1/16 TU = 64us
3280 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
3284 if (Offset == (BCN_TBTT_OFFSET-1))
3286 BCN_TIME_CFG_STRUC csr;
3288 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
3289 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU
3290 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);