2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 *************************************************************************
28 #include "../rt_config.h"
30 #define MAX_TX_IN_TBTT (16)
33 UCHAR SNAP_802_1H[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
34 UCHAR SNAP_BRIDGE_TUNNEL[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8};
35 // Add Cisco Aironet SNAP heade for CCX2 support
36 UCHAR SNAP_AIRONET[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00};
37 UCHAR CKIP_LLC_SNAP[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02};
38 UCHAR EAPOL_LLC_SNAP[]= {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e};
39 UCHAR EAPOL[] = {0x88, 0x8e};
40 UCHAR TPID[] = {0x81, 0x00}; /* VLAN related */
42 UCHAR IPX[] = {0x81, 0x37};
43 UCHAR APPLE_TALK[] = {0x80, 0xf3};
44 UCHAR RateIdToPlcpSignal[12] = {
45 0, /* RATE_1 */ 1, /* RATE_2 */ 2, /* RATE_5_5 */ 3, /* RATE_11 */ // see BBP spec
46 11, /* RATE_6 */ 15, /* RATE_9 */ 10, /* RATE_12 */ 14, /* RATE_18 */ // see IEEE802.11a-1999 p.14
47 9, /* RATE_24 */ 13, /* RATE_36 */ 8, /* RATE_48 */ 12 /* RATE_54 */ }; // see IEEE802.11a-1999 p.14
49 UCHAR OfdmSignalToRateId[16] = {
50 RATE_54, RATE_54, RATE_54, RATE_54, // OFDM PLCP Signal = 0, 1, 2, 3 respectively
51 RATE_54, RATE_54, RATE_54, RATE_54, // OFDM PLCP Signal = 4, 5, 6, 7 respectively
52 RATE_48, RATE_24, RATE_12, RATE_6, // OFDM PLCP Signal = 8, 9, 10, 11 respectively
53 RATE_54, RATE_36, RATE_18, RATE_9, // OFDM PLCP Signal = 12, 13, 14, 15 respectively
56 UCHAR OfdmRateToRxwiMCS[12] = {
58 0, 1, 2, 3, // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3
59 4, 5, 6, 7, // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7
61 UCHAR RxwiMCSToOfdmRate[12] = {
62 RATE_6, RATE_9, RATE_12, RATE_18,
63 RATE_24, RATE_36, RATE_48, RATE_54, // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3
64 4, 5, 6, 7, // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7
67 char* MCSToMbps[] = {"1Mbps","2Mbps","5.5Mbps","11Mbps","06Mbps","09Mbps","12Mbps","18Mbps","24Mbps","36Mbps","48Mbps","54Mbps","MM-0","MM-1","MM-2","MM-3","MM-4","MM-5","MM-6","MM-7","MM-8","MM-9","MM-10","MM-11","MM-12","MM-13","MM-14","MM-15","MM-32","ee1","ee2","ee3"};
69 UCHAR default_cwmin[]={CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1, CW_MIN_IN_BITS-2};
70 UCHAR default_sta_aifsn[]={3,7,2,2};
72 UCHAR MapUserPriorityToAccessCategory[8] = {QID_AC_BE, QID_AC_BK, QID_AC_BK, QID_AC_BE, QID_AC_VI, QID_AC_VI, QID_AC_VO, QID_AC_VO};
76 ========================================================================
79 API for MLME to transmit management frame to AP (BSS Mode)
80 or station (IBSS Mode)
83 pAd Pointer to our adapter
84 pData Pointer to the outgoing 802.11 frame
85 Length Size of outgoing management frame
97 ========================================================================
99 NDIS_STATUS MiniportMMRequest(
100 IN PRTMP_ADAPTER pAd,
105 PNDIS_PACKET pPacket;
106 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
108 unsigned long IrqFlags = 0;
110 UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN];
112 ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
118 IrqState = pAd->irq_disabled;
120 if ((pAd->MACVersion == 0x28600100) && (!IrqState))
121 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
125 // Reset is in progress, stop immediately
126 if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
127 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)||
128 !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
130 Status = NDIS_STATUS_FAILURE;
134 // Check Free priority queue
135 // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing.
138 if (pAd->MACVersion == 0x28600100)
140 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
144 FreeNum = GET_MGMTRING_FREENO(pAd);
149 // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870
150 NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE));
151 Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE), pData, Length);
152 if (Status != NDIS_STATUS_SUCCESS)
154 DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
158 //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
159 //pAd->CommonCfg.MlmeRate = RATE_2;
162 Status = MlmeHardTransmit(pAd, QueIdx, pPacket);
163 if (Status != NDIS_STATUS_SUCCESS)
164 RTMPFreeNdisPacket(pAd, pPacket);
168 pAd->RalinkCounters.MgmtRingFullCount++;
169 DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n",
170 QueIdx, pAd->RalinkCounters.MgmtRingFullCount));
176 if ((pAd->MACVersion == 0x28600100) && (!IrqState))
177 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
183 NDIS_STATUS MiniportMMRequestUnlock(
184 IN PRTMP_ADAPTER pAd,
189 PNDIS_PACKET pPacket;
190 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
197 ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
201 // Reset is in progress, stop immediately
202 if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
203 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)||
204 !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
206 Status = NDIS_STATUS_FAILURE;
210 // Check Free priority queue
211 // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing.
213 if (pAd->MACVersion == 0x28600100)
215 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
216 SW_TX_IDX = pAd->TxRing[QueIdx].TxCpuIdx;
217 pTxD = (PTXD_STRUC) pAd->TxRing[QueIdx].Cell[SW_TX_IDX].AllocVa;
221 FreeNum = GET_MGMTRING_FREENO(pAd);
222 SW_TX_IDX = pAd->MgmtRing.TxCpuIdx;
223 pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[SW_TX_IDX].AllocVa;
227 NdisZeroMemory(&TXWI, TXWI_SIZE);
228 Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&TXWI, TXWI_SIZE, pData, Length);
229 if (Status != NDIS_STATUS_SUCCESS)
231 DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
235 Status = MlmeHardTransmit(pAd, QueIdx, pPacket);
236 if (Status != NDIS_STATUS_SUCCESS)
237 RTMPFreeNdisPacket(pAd, pPacket);
241 pAd->RalinkCounters.MgmtRingFullCount++;
242 DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing\n", QueIdx));
253 ========================================================================
256 Copy frame from waiting queue into relative ring buffer and set
257 appropriate ASIC register to kick hardware transmit function
260 pAd Pointer to our adapter
261 pBuffer Pointer to memory of outgoing frame
262 Length Size of outgoing management frame
270 IRQL = DISPATCH_LEVEL
274 ========================================================================
276 NDIS_STATUS MlmeHardTransmit(
277 IN PRTMP_ADAPTER pAd,
279 IN PNDIS_PACKET pPacket)
281 if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
283 return NDIS_STATUS_FAILURE;
286 if ( pAd->MACVersion == 0x28600100 )
287 return MlmeHardTransmitTxRing(pAd,QueIdx,pPacket);
289 return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
294 NDIS_STATUS MlmeHardTransmitTxRing(
295 IN PRTMP_ADAPTER pAd,
297 IN PNDIS_PACKET pPacket)
299 PACKET_INFO PacketInfo;
303 PHEADER_802_11 pHeader_802_11;
304 BOOLEAN bAckRequired, bInsertTimestamp;
307 ULONG SwIdx = pAd->TxRing[QueIdx].TxCpuIdx;
308 PTXWI_STRUC pFirstTxWI;
310 MAC_TABLE_ENTRY *pMacEntry = NULL;
313 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
315 if (pSrcBufVA == NULL)
317 // The buffer shouldn't be NULL
318 return NDIS_STATUS_FAILURE;
321 // Make sure MGMT ring resource won't be used by other threads
322 //NdisAcquireSpinLock(&pAd->TxRingLock);
324 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
328 //NdisReleaseSpinLock(&pAd->TxRingLock);
329 return NDIS_STATUS_FAILURE;
332 SwIdx = pAd->TxRing[QueIdx].TxCpuIdx;
334 pTxD = (PTXD_STRUC) pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa;
336 if (pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket)
338 printk("MlmeHardTransmit Error\n");
339 return NDIS_STATUS_FAILURE;
342 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
344 // outgoing frame always wakeup PHY to prevent frame lost
345 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
346 AsicForceWakeup(pAd, FROM_TX);
349 pFirstTxWI =(PTXWI_STRUC)pSrcBufVA;
351 pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXWI_SIZE);
352 if (pHeader_802_11->Addr1[0] & 0x01)
354 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
358 MlmeRate = pAd->CommonCfg.MlmeRate;
361 if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
362 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
364 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
367 // Verify Mlme rate for a / g bands.
368 if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
372 // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
373 // Snice it's been set to 0 while on MgtMacHeaderInit
374 // By the way this will cause frame to be send on PWR_SAVE failed.
377 // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
379 // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
380 if (pHeader_802_11->FC.Type != BTYPE_DATA)
382 if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_REQ) || !(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
384 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
388 pHeader_802_11->FC.PwrMgmt = pAd->CommonCfg.bAPSDForcePowerSave;
392 bInsertTimestamp = FALSE;
393 if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
395 bAckRequired = FALSE;
397 else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
399 if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
401 bAckRequired = FALSE;
402 pHeader_802_11->Duration = 0;
407 pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
408 if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
410 bInsertTimestamp = TRUE;
414 pHeader_802_11->Sequence = pAd->Sequence++;
415 if (pAd->Sequence > 0xfff)
417 // Before radar detection done, mgmt frame can not be sent but probe req
418 // Because we need to use probe req to trigger driver to send probe req in passive scan
419 if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
420 && (pAd->CommonCfg.bIEEE80211H == 1)
421 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
423 DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
424 return (NDIS_STATUS_FAILURE);
428 // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
429 // should always has only one ohysical buffer, and the whole frame size equals
430 // to the first scatter buffer size
433 // Initialize TX Descriptor
434 // For inter-frame gap, the number is for this frame and next frame
435 // For MLME rate, we will fix as 2Mb to match other vendor's implement
437 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
438 // Only beacon use Nseq=TRUE. So here we use Nseq=FALSE.
439 if (pMacEntry == NULL)
441 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
442 0, RESERVED_WCID, (SrcBufLen - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
446 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
447 bInsertTimestamp, FALSE, bAckRequired, FALSE,
448 0, pMacEntry->Aid, (SrcBufLen - TXWI_SIZE),
449 pMacEntry->MaxHTPhyMode.field.MCS, 0,
450 (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
451 IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
454 pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket = pPacket;
455 pAd->TxRing[QueIdx].Cell[SwIdx].pNextNdisPacket = NULL;
457 SrcBufPA = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE);
460 RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_EDCA);
463 pTxD->SDLen0 = SrcBufLen;
465 pTxD->SDPtr0 = SrcBufPA;
468 pAd->RalinkCounters.KickTxCount++;
469 pAd->RalinkCounters.OneSecTxDoneCount++;
471 // Increase TX_CTX_IDX, but write to register later.
472 INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE);
474 RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx*0x10, pAd->TxRing[QueIdx].TxCpuIdx);
476 return NDIS_STATUS_SUCCESS;
480 NDIS_STATUS MlmeHardTransmitMgmtRing(
481 IN PRTMP_ADAPTER pAd,
483 IN PNDIS_PACKET pPacket)
485 PACKET_INFO PacketInfo;
488 PHEADER_802_11 pHeader_802_11;
489 BOOLEAN bAckRequired, bInsertTimestamp;
491 PTXWI_STRUC pFirstTxWI;
492 MAC_TABLE_ENTRY *pMacEntry = NULL;
494 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
495 RTMP_SEM_LOCK(&pAd->MgmtRingLock);
498 if (pSrcBufVA == NULL)
500 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
501 return NDIS_STATUS_FAILURE;
504 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
506 // outgoing frame always wakeup PHY to prevent frame lost
507 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
508 AsicForceWakeup(pAd, FROM_TX);
511 pFirstTxWI = (PTXWI_STRUC)(pSrcBufVA + TXINFO_SIZE);
512 pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); //TXWI_SIZE);
514 if (pHeader_802_11->Addr1[0] & 0x01)
516 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
520 MlmeRate = pAd->CommonCfg.MlmeRate;
523 // Verify Mlme rate for a / g bands.
524 if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
527 if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
528 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
530 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
533 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
535 // Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode.
536 if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED
537 #ifdef DOT11_N_SUPPORT
538 || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED
539 #endif // DOT11_N_SUPPORT //
542 if (pAd->LatchRfRegs.Channel > 14)
543 pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
545 pAd->CommonCfg.MlmeTransmit.field.MODE = 0;
550 // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
551 // Snice it's been set to 0 while on MgtMacHeaderInit
552 // By the way this will cause frame to be send on PWR_SAVE failed.
554 // pHeader_802_11->FC.PwrMgmt = 0; // (pAd->StaCfg.Psm == PWR_SAVE);
556 // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
558 // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
559 if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL))
561 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
562 (pHeader_802_11->FC.SubType == SUBTYPE_ACTION))
563 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
565 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
568 bInsertTimestamp = FALSE;
569 if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
571 //Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue.
572 if ((pAd->OpMode == OPMODE_STA) && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL))
574 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
576 bAckRequired = FALSE;
578 else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
580 if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
582 bAckRequired = FALSE;
583 pHeader_802_11->Duration = 0;
588 pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
589 if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
591 bInsertTimestamp = TRUE;
596 pHeader_802_11->Sequence = pAd->Sequence++;
597 if (pAd->Sequence >0xfff)
600 // Before radar detection done, mgmt frame can not be sent but probe req
601 // Because we need to use probe req to trigger driver to send probe req in passive scan
602 if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
603 && (pAd->CommonCfg.bIEEE80211H == 1)
604 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
606 DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
607 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
608 return (NDIS_STATUS_FAILURE);
612 // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
613 // should always has only one ohysical buffer, and the whole frame size equals
614 // to the first scatter buffer size
617 // Initialize TX Descriptor
618 // For inter-frame gap, the number is for this frame and next frame
619 // For MLME rate, we will fix as 2Mb to match other vendor's implement
621 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
622 if (pMacEntry == NULL)
624 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
625 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
629 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
630 bInsertTimestamp, FALSE, bAckRequired, FALSE,
631 0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE),
632 pMacEntry->MaxHTPhyMode.field.MCS, 0,
633 (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
634 IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
637 // Now do hardware-depened kick out.
638 HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen);
640 // Make sure to release MGMT ring resource
641 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
642 return NDIS_STATUS_SUCCESS;
646 /********************************************************************************
648 New DeQueue Procedures.
650 ********************************************************************************/
652 #define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \
654 if (bIntContext == FALSE) \
655 RTMP_IRQ_LOCK((lock), IrqFlags); \
658 #define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \
660 if (bIntContext == FALSE) \
661 RTMP_IRQ_UNLOCK((lock), IrqFlags); \
665 ========================================================================
666 Tx Path design algorithm:
667 Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal),
668 Specific Packet Type. Following show the classification rule and policy for each kinds of packets.
669 Classification Rule=>
670 Multicast: (*addr1 & 0x01) == 0x01
671 Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc.
672 11N Rate : If peer support HT
673 (1).AMPDU -- If TXBA is negotiated.
674 (2).AMSDU -- If AMSDU is capable for both peer and ourself.
675 *). AMSDU can embedded in a AMPDU, but now we didn't support it.
676 (3).Normal -- Other packets which send as 11n rate.
678 B/G Rate : If peer is b/g only.
679 (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6
680 (2).Normal -- Other packets which send as b/g rate.
682 The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
684 Classified Packet Handle Rule=>
686 No ACK, //pTxBlk->bAckRequired = FALSE;
687 No WMM, //pTxBlk->bWMM = FALSE;
688 No piggyback, //pTxBlk->bPiggyBack = FALSE;
689 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
690 Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use
691 the same policy to handle it.
692 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
695 No piggyback, //pTxBlk->bPiggyBack = FALSE;
707 ========================================================================
709 static UCHAR TxPktClassification(
710 IN RTMP_ADAPTER *pAd,
711 IN PNDIS_PACKET pPacket)
713 UCHAR TxFrameType = TX_UNKOWN_FRAME;
715 MAC_TABLE_ENTRY *pMacEntry = NULL;
716 #ifdef DOT11_N_SUPPORT
717 BOOLEAN bHTRate = FALSE;
718 #endif // DOT11_N_SUPPORT //
720 Wcid = RTMP_GET_PACKET_WCID(pPacket);
721 if (Wcid == MCAST_WCID)
722 { // Handle for RA is Broadcast/Multicast Address.
723 return TX_MCAST_FRAME;
726 // Handle for unicast packets
727 pMacEntry = &pAd->MacTab.Content[Wcid];
728 if (RTMP_GET_PACKET_LOWRATE(pPacket))
729 { // It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame
730 TxFrameType = TX_LEGACY_FRAME;
732 #ifdef DOT11_N_SUPPORT
733 else if (IS_HT_RATE(pMacEntry))
734 { // it's a 11n capable packet
736 // Depends on HTPhyMode to check if the peer support the HTRate transmission.
737 // Currently didn't support A-MSDU embedded in A-MPDU
739 if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE))
740 TxFrameType = TX_LEGACY_FRAME;
741 #ifdef UAPSD_AP_SUPPORT
742 else if (RTMP_GET_PACKET_EOSP(pPacket))
743 TxFrameType = TX_LEGACY_FRAME;
744 #endif // UAPSD_AP_SUPPORT //
745 else if((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0)
746 return TX_AMPDU_FRAME;
747 else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED))
748 return TX_AMSDU_FRAME;
750 TxFrameType = TX_LEGACY_FRAME;
752 #endif // DOT11_N_SUPPORT //
754 { // it's a legacy b/g packet.
755 if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) &&
756 (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) &&
757 (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
758 { // if peer support Ralink Aggregation, we use it.
759 TxFrameType = TX_RALINK_FRAME;
763 TxFrameType = TX_LEGACY_FRAME;
767 // Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU.
768 if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) && (TxFrameType == TX_LEGACY_FRAME))
769 TxFrameType = TX_FRAG_FRAME;
775 BOOLEAN RTMP_FillTxBlkInfo(
776 IN RTMP_ADAPTER *pAd,
779 PACKET_INFO PacketInfo;
780 PNDIS_PACKET pPacket;
781 PMAC_TABLE_ENTRY pMacEntry = NULL;
783 pPacket = pTxBlk->pPacket;
784 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
786 pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket);
787 pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket);
788 pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket);
789 pTxBlk->FrameGap = IFS_HTTXOP; // ASIC determine Frame Gap
791 if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket))
792 TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame);
794 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame);
796 // Default to clear this flag
797 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS);
800 if (pTxBlk->Wcid == MCAST_WCID)
802 pTxBlk->pMacEntry = NULL;
804 #ifdef MCAST_RATE_SPECIFIC
805 PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket);
806 if (((*pDA & 0x01) == 0x01) && (*pDA != 0xff))
807 pTxBlk->pTransmit = &pAd->CommonCfg.MCastPhyMode;
809 #endif // MCAST_RATE_SPECIFIC //
810 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
813 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); // AckRequired = FALSE, when broadcast packet in Adhoc mode.
814 //TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate);
815 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag);
816 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
817 if (RTMP_GET_PACKET_MOREDATA(pPacket))
819 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
825 pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
826 pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode;
828 pMacEntry = pTxBlk->pMacEntry;
831 // For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK.
832 if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK)
833 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
835 TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired);
838 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
841 // If support WMM, enable it.
842 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
843 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM);
847 if (pTxBlk->TxFrameType == TX_LEGACY_FRAME)
849 if ( (RTMP_GET_PACKET_LOWRATE(pPacket)) ||
850 ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1)))
851 { // Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate.
852 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
853 #ifdef DOT11_N_SUPPORT
854 // Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it???
855 if (IS_HT_STA(pTxBlk->pMacEntry) &&
856 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) &&
857 ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)))
859 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
860 TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS);
862 #endif // DOT11_N_SUPPORT //
865 #ifdef DOT11_N_SUPPORT
866 if ( (IS_HT_RATE(pMacEntry) == FALSE) &&
867 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE)))
868 { // Currently piggy-back only support when peer is operate in b/g mode.
869 TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack);
871 #endif // DOT11_N_SUPPORT //
873 if (RTMP_GET_PACKET_MOREDATA(pPacket))
875 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
877 #ifdef UAPSD_AP_SUPPORT
878 if (RTMP_GET_PACKET_EOSP(pPacket))
880 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP);
882 #endif // UAPSD_AP_SUPPORT //
884 else if (pTxBlk->TxFrameType == TX_FRAG_FRAME)
886 TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag);
889 pMacEntry->DebugTxCount++;
896 BOOLEAN CanDoAggregateTransmit(
897 IN RTMP_ADAPTER *pAd,
898 IN NDIS_PACKET *pPacket,
902 //printk("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType);
904 if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
907 if (RTMP_GET_PACKET_DHCP(pPacket) ||
908 RTMP_GET_PACKET_EAPOL(pPacket) ||
909 RTMP_GET_PACKET_WAI(pPacket))
912 if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) &&
913 ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100)))
914 { // For AMSDU, allow the packets with total length < max-amsdu size
918 if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) &&
919 (pTxBlk->TxPacketList.Number == 2))
920 { // For RALINK-Aggregation, allow two frames in one batch.
924 if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP
932 ========================================================================
935 To do the enqueue operation and extract the first item of waiting
936 list. If a number of available shared memory segments could meet
937 the request of extracted item, the extracted item will be fragmented
938 into shared memory segments.
941 pAd Pointer to our adapter
942 pQueue Pointer to Waiting Queue
947 IRQL = DISPATCH_LEVEL
951 ========================================================================
953 VOID RTMPDeQueuePacket(
954 IN PRTMP_ADAPTER pAd,
955 IN BOOLEAN bIntContext,
956 IN UCHAR QIdx, /* BulkOutPipeId */
957 IN UCHAR Max_Tx_Packets)
959 PQUEUE_ENTRY pEntry = NULL;
960 PNDIS_PACKET pPacket;
961 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
963 PQUEUE_HEADER pQueue;
964 ULONG FreeNumber[NUM_OF_TX_RING];
965 UCHAR QueIdx, sQIdx, eQIdx;
966 unsigned long IrqFlags = 0;
967 BOOLEAN hasTxDesc = FALSE;
973 RtmpDiagStruct *pDiagStruct = &pAd->DiagStruct;
977 if (QIdx == NUM_OF_TX_RING)
980 eQIdx = 3; // 4 ACs, start from 0.
984 sQIdx = eQIdx = QIdx;
987 for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++)
991 RT28XX_START_DEQUEUE(pAd, QueIdx, IrqFlags);
994 firstRound = ((QueIdx == 0) ? TRUE : FALSE);
995 #endif // DBG_DIAGNOSE //
999 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |
1000 fRTMP_ADAPTER_RADIO_OFF |
1001 fRTMP_ADAPTER_RESET_IN_PROGRESS |
1002 fRTMP_ADAPTER_HALT_IN_PROGRESS |
1003 fRTMP_ADAPTER_NIC_NOT_EXIST))))
1005 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
1009 if (Count >= Max_Tx_Packets)
1012 DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1013 if (&pAd->TxSwQueue[QueIdx] == NULL)
1016 if (firstRound == TRUE)
1017 pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][0]++;
1018 #endif // DBG_DIAGNOSE //
1019 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1023 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
1026 if (firstRound == TRUE)
1028 UCHAR txDescNumLevel, txSwQNumLevel;
1030 txDescNumLevel = (TX_RING_SIZE - FreeNumber[QueIdx]); // Number of occupied hw desc.
1031 txDescNumLevel = ((txDescNumLevel <=15) ? txDescNumLevel : 15);
1032 pDiagStruct->TxDescCnt[pDiagStruct->ArrayCurIdx][txDescNumLevel]++;
1034 txSwQNumLevel = ((pAd->TxSwQueue[QueIdx].Number <=7) ? pAd->TxSwQueue[QueIdx].Number : 8);
1035 pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][txSwQNumLevel]++;
1039 #endif // DBG_DIAGNOSE //
1041 if (FreeNumber[QueIdx] <= 5)
1043 // free Tx(QueIdx) resources
1044 RTMPFreeTXDUponTxDmaDone(pAd, QueIdx);
1045 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
1048 // probe the Queue Head
1049 pQueue = &pAd->TxSwQueue[QueIdx];
1050 if ((pEntry = pQueue->Head) == NULL)
1052 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1057 NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK));
1058 pTxBlk->QueIdx = QueIdx;
1060 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
1062 // Early check to make sure we have enoguh Tx Resource.
1063 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
1066 pAd->PrivateInfo.TxRingFullCnt++;
1068 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1073 pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
1074 pEntry = RemoveHeadQueue(pQueue);
1075 pTxBlk->TotalFrameNum++;
1076 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
1077 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
1078 pTxBlk->pPacket = pPacket;
1079 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
1081 if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME)
1083 // Enhance SW Aggregation Mechanism
1084 if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType))
1086 InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
1087 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1092 if((pEntry = pQueue->Head) == NULL)
1095 // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation.
1096 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
1097 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
1098 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
1099 if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE))
1102 //Remove the packet from the TxSwQueue and insert into pTxBlk
1103 pEntry = RemoveHeadQueue(pQueue);
1105 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
1106 pTxBlk->TotalFrameNum++;
1107 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
1108 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
1109 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
1112 if (pTxBlk->TxPacketList.Number == 1)
1113 pTxBlk->TxFrameType = TX_LEGACY_FRAME;
1117 Count += pTxBlk->TxPacketList.Number;
1119 // Do HardTransmit now.
1120 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1121 Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
1123 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1124 // static rate also need NICUpdateFifoStaCounters() function.
1125 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
1126 NICUpdateFifoStaCounters(pAd);
1129 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
1136 ========================================================================
1138 Routine Description:
1139 Calculates the duration which is required to transmit out frames
1140 with given size and specified rate.
1143 pAd Pointer to our adapter
1145 Size Frame size in units of byte
1148 Duration number in units of usec
1150 IRQL = PASSIVE_LEVEL
1151 IRQL = DISPATCH_LEVEL
1155 ========================================================================
1157 USHORT RTMPCalcDuration(
1158 IN PRTMP_ADAPTER pAd,
1164 if (Rate < RATE_FIRST_OFDM_RATE) // CCK
1166 if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED))
1167 Duration = 96; // 72+24 preamble+plcp
1169 Duration = 192; // 144+48 preamble+plcp
1171 Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]);
1172 if ((Size << 4) % RateIdTo500Kbps[Rate])
1175 else if (Rate <= RATE_LAST_OFDM_RATE)// OFDM rates
1177 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
1178 Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
1179 if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
1184 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
1187 return (USHORT)Duration;
1192 ========================================================================
1194 Routine Description:
1195 Calculates the duration which is required to transmit out frames
1196 with given size and specified rate.
1199 pTxWI Pointer to head of each MPDU to HW.
1200 Ack Setting for Ack requirement bit
1201 Fragment Setting for Fragment bit
1202 RetryMode Setting for retry mode
1203 Ifs Setting for IFS gap
1204 Rate Setting for transmit rate
1205 Service Setting for service
1207 TxPreamble Short or Long preamble when using CCK rates
1208 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1213 IRQL = PASSIVE_LEVEL
1214 IRQL = DISPATCH_LEVEL
1216 See also : BASmartHardTransmit() !!!
1218 ========================================================================
1221 IN PRTMP_ADAPTER pAd,
1222 IN PTXWI_STRUC pOutTxWI,
1225 IN BOOLEAN InsTimestamp,
1228 IN BOOLEAN NSeq, // HW new a sequence.
1237 IN HTTRANSMIT_SETTING *pTransmit)
1239 PMAC_TABLE_ENTRY pMac = NULL;
1243 if (WCID < MAX_LEN_OF_MAC_TABLE)
1244 pMac = &pAd->MacTab.Content[WCID];
1247 // Always use Long preamble before verifiation short preamble functionality works well.
1248 // Todo: remove the following line if short preamble functionality works
1250 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1251 NdisZeroMemory(&TxWI, TXWI_SIZE);
1256 pTxWI->CFACK = CFACK;
1257 pTxWI->TS= InsTimestamp;
1258 pTxWI->AMPDU = AMPDU;
1260 pTxWI->txop= Txopmode;
1263 // John tune the performace with Intel Client in 20 MHz performance
1264 #ifdef DOT11_N_SUPPORT
1265 BASize = pAd->CommonCfg.TxBASize;
1269 pTxWI->BAWinSize = BASize;
1270 pTxWI->ShortGI = pTransmit->field.ShortGI;
1271 pTxWI->STBC = pTransmit->field.STBC;
1272 #endif // DOT11_N_SUPPORT //
1274 pTxWI->WirelessCliID = WCID;
1275 pTxWI->MPDUtotalByteCount = Length;
1276 pTxWI->PacketId = PID;
1278 // If CCK or OFDM, BW must be 20
1279 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1281 pTxWI->MCS = pTransmit->field.MCS;
1282 pTxWI->PHYMODE = pTransmit->field.MODE;
1283 pTxWI->CFACK = CfAck;
1285 #ifdef DOT11_N_SUPPORT
1288 if (pAd->CommonCfg.bMIMOPSEnable)
1290 if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1292 // Dynamic MIMO Power Save Mode
1295 else if (pMac->MmpsMode == MMPS_STATIC)
1297 // Static MIMO Power Save Mode
1298 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1305 //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;
1306 if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled))
1308 pTxWI->MpduDensity = 7;
1312 pTxWI->MpduDensity = pMac->MpduDensity;
1315 #endif // DOT11_N_SUPPORT //
1317 pTxWI->PacketId = pTxWI->MCS;
1318 NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC));
1322 VOID RTMPWriteTxWI_Data(
1323 IN PRTMP_ADAPTER pAd,
1324 IN OUT PTXWI_STRUC pTxWI,
1327 HTTRANSMIT_SETTING *pTransmit;
1328 PMAC_TABLE_ENTRY pMacEntry;
1329 #ifdef DOT11_N_SUPPORT
1331 #endif // DOT11_N_SUPPORT //
1336 pTransmit = pTxBlk->pTransmit;
1337 pMacEntry = pTxBlk->pMacEntry;
1341 // Always use Long preamble before verifiation short preamble functionality works well.
1342 // Todo: remove the following line if short preamble functionality works
1344 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1345 NdisZeroMemory(pTxWI, TXWI_SIZE);
1347 pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1348 pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1349 pTxWI->txop = pTxBlk->FrameGap;
1351 pTxWI->WirelessCliID = pTxBlk->Wcid;
1353 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1354 pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
1356 // If CCK or OFDM, BW must be 20
1357 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1358 #ifdef DOT11_N_SUPPORT
1359 pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
1361 // John tune the performace with Intel Client in 20 MHz performance
1362 BASize = pAd->CommonCfg.TxBASize;
1363 if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry))
1365 UCHAR RABAOriIdx = 0; //The RA's BA Originator table index.
1367 RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
1368 BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1371 pTxWI->TxBF = pTransmit->field.TxBF;
1372 pTxWI->BAWinSize = BASize;
1373 pTxWI->ShortGI = pTransmit->field.ShortGI;
1374 pTxWI->STBC = pTransmit->field.STBC;
1375 #endif // DOT11_N_SUPPORT //
1377 pTxWI->MCS = pTransmit->field.MCS;
1378 pTxWI->PHYMODE = pTransmit->field.MODE;
1380 #ifdef DOT11_N_SUPPORT
1383 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1385 // Dynamic MIMO Power Save Mode
1388 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1390 // Static MIMO Power Save Mode
1391 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1398 if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled))
1400 pTxWI->MpduDensity = 7;
1404 pTxWI->MpduDensity = pMacEntry->MpduDensity;
1407 #endif // DOT11_N_SUPPORT //
1410 if (pTxBlk->QueIdx== 0)
1412 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1413 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1415 #endif // DBG_DIAGNOSE //
1417 // for rate adapation
1418 pTxWI->PacketId = pTxWI->MCS;
1422 VOID RTMPWriteTxWI_Cache(
1423 IN PRTMP_ADAPTER pAd,
1424 IN OUT PTXWI_STRUC pTxWI,
1427 PHTTRANSMIT_SETTING pTransmit;
1428 PMAC_TABLE_ENTRY pMacEntry;
1433 pMacEntry = pTxBlk->pMacEntry;
1434 pTransmit = pTxBlk->pTransmit;
1436 if (pMacEntry->bAutoTxRateSwitch)
1438 pTxWI->txop = IFS_HTTXOP;
1440 // If CCK or OFDM, BW must be 20
1441 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1442 pTxWI->ShortGI = pTransmit->field.ShortGI;
1443 pTxWI->STBC = pTransmit->field.STBC;
1445 pTxWI->MCS = pTransmit->field.MCS;
1446 pTxWI->PHYMODE = pTransmit->field.MODE;
1448 // set PID for TxRateSwitching
1449 pTxWI->PacketId = pTransmit->field.MCS;
1452 #ifdef DOT11_N_SUPPORT
1453 pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE);
1456 if (pAd->CommonCfg.bMIMOPSEnable)
1458 // MIMO Power Save Mode
1459 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1461 // Dynamic MIMO Power Save Mode
1464 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1466 // Static MIMO Power Save Mode
1467 if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7))
1474 #endif // DOT11_N_SUPPORT //
1477 if (pTxBlk->QueIdx== 0)
1479 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1480 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1482 #endif // DBG_DIAGNOSE //
1484 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1490 ========================================================================
1492 Routine Description:
1493 Calculates the duration which is required to transmit out frames
1494 with given size and specified rate.
1497 pTxD Pointer to transmit descriptor
1498 Ack Setting for Ack requirement bit
1499 Fragment Setting for Fragment bit
1500 RetryMode Setting for retry mode
1501 Ifs Setting for IFS gap
1502 Rate Setting for transmit rate
1503 Service Setting for service
1505 TxPreamble Short or Long preamble when using CCK rates
1506 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1511 IRQL = PASSIVE_LEVEL
1512 IRQL = DISPATCH_LEVEL
1514 ========================================================================
1516 VOID RTMPWriteTxDescriptor(
1517 IN PRTMP_ADAPTER pAd,
1523 // Always use Long preamble before verifiation short preamble functionality works well.
1524 // Todo: remove the following line if short preamble functionality works
1526 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1528 pTxD->WIV = (bWIV) ? 1: 0;
1529 pTxD->QSEL= (QueueSEL);
1530 if (pAd->bGenOneHCCA == TRUE)
1531 pTxD->QSEL= FIFO_HCCA;
1536 // should be called only when -
1537 // 1. MEADIA_CONNECTED
1538 // 2. AGGREGATION_IN_USED
1539 // 3. Fragmentation not in used
1540 // 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible
1541 BOOLEAN TxFrameIsAggregatible(
1542 IN PRTMP_ADAPTER pAd,
1543 IN PUCHAR pPrevAddr1,
1547 // can't aggregate EAPOL (802.1x) frame
1548 if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1551 // can't aggregate multicast/broadcast frame
1552 if (p8023hdr[0] & 0x01)
1555 if (INFRA_ON(pAd)) // must be unicast to AP
1557 else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA
1565 ========================================================================
1567 Routine Description:
1568 Check the MSDU Aggregation policy
1569 1.HT aggregation is A-MSDU
1570 2.legaacy rate aggregation is software aggregation by Ralink.
1578 ========================================================================
1580 BOOLEAN PeerIsAggreOn(
1581 IN PRTMP_ADAPTER pAd,
1583 IN PMAC_TABLE_ENTRY pMacEntry)
1585 ULONG AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
1587 if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags))
1589 #ifdef DOT11_N_SUPPORT
1590 if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX)
1594 #endif // DOT11_N_SUPPORT //
1596 #ifdef AGGREGATION_SUPPORT
1597 if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
1598 { // legacy Ralink Aggregation support
1601 #endif // AGGREGATION_SUPPORT //
1610 ========================================================================
1612 Routine Description:
1613 Check and fine the packet waiting in SW queue with highest priority
1616 pAd Pointer to our adapter
1619 pQueue Pointer to Waiting Queue
1621 IRQL = DISPATCH_LEVEL
1625 ========================================================================
1627 PQUEUE_HEADER RTMPCheckTxSwQueue(
1628 IN PRTMP_ADAPTER pAd,
1634 Number = pAd->TxSwQueue[QID_AC_BK].Number
1635 + pAd->TxSwQueue[QID_AC_BE].Number
1636 + pAd->TxSwQueue[QID_AC_VI].Number
1637 + pAd->TxSwQueue[QID_AC_VO].Number
1638 + pAd->TxSwQueue[QID_HCCA].Number;
1640 if (pAd->TxSwQueue[QID_AC_VO].Head != NULL)
1642 *pQueIdx = QID_AC_VO;
1643 return (&pAd->TxSwQueue[QID_AC_VO]);
1645 else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL)
1647 *pQueIdx = QID_AC_VI;
1648 return (&pAd->TxSwQueue[QID_AC_VI]);
1650 else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL)
1652 *pQueIdx = QID_AC_BE;
1653 return (&pAd->TxSwQueue[QID_AC_BE]);
1655 else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL)
1657 *pQueIdx = QID_AC_BK;
1658 return (&pAd->TxSwQueue[QID_AC_BK]);
1660 else if (pAd->TxSwQueue[QID_HCCA].Head != NULL)
1662 *pQueIdx = QID_HCCA;
1663 return (&pAd->TxSwQueue[QID_HCCA]);
1666 // No packet pending in Tx Sw queue
1667 *pQueIdx = QID_AC_BK;
1673 BOOLEAN RTMPFreeTXDUponTxDmaDone(
1674 IN PRTMP_ADAPTER pAd,
1677 PRTMP_TX_RING pTxRing;
1679 PNDIS_PACKET pPacket;
1681 TXD_STRUC TxD, *pOriTxD;
1683 BOOLEAN bReschedule = FALSE;
1686 ASSERT(QueIdx < NUM_OF_TX_RING);
1687 pTxRing = &pAd->TxRing[QueIdx];
1689 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF, &pTxRing->TxDmaIdx);
1690 while (pTxRing->TxSwFreeIdx != pTxRing->TxDmaIdx)
1692 // static rate also need NICUpdateFifoStaCounters() function.
1693 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
1694 NICUpdateFifoStaCounters(pAd);
1696 /* Note : If (pAd->ate.bQATxStart == TRUE), we will never reach here. */
1698 pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
1700 NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC));
1705 /*====================================================================*/
1707 pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket;
1710 #ifdef CONFIG_5VT_ENHANCE
1711 if (RTMP_GET_PACKET_5VT(pPacket))
1712 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE);
1714 #endif // CONFIG_5VT_ENHANCE //
1715 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
1716 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1718 //Always assign pNdisPacket as NULL after clear
1719 pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket = NULL;
1721 pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket;
1723 ASSERT(pPacket == NULL);
1726 #ifdef CONFIG_5VT_ENHANCE
1727 if (RTMP_GET_PACKET_5VT(pPacket))
1728 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE);
1730 #endif // CONFIG_5VT_ENHANCE //
1731 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
1732 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1734 //Always assign pNextNdisPacket as NULL after clear
1735 pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL;
1737 /*====================================================================*/
1739 pAd->RalinkCounters.TransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0);
1740 pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++;
1741 INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE);
1742 /* get tx_tdx_idx again */
1743 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &pTxRing->TxDmaIdx);
1745 NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC));
1755 ========================================================================
1757 Routine Description:
1758 Process TX Rings DMA Done interrupt, running in DPC level
1761 Adapter Pointer to our adapter
1766 IRQL = DISPATCH_LEVEL
1768 ========================================================================
1770 BOOLEAN RTMPHandleTxRingDmaDoneInterrupt(
1771 IN PRTMP_ADAPTER pAd,
1772 IN INT_SOURCE_CSR_STRUC TxRingBitmap)
1774 unsigned long IrqFlags;
1775 BOOLEAN bReschedule = FALSE;
1777 // Make sure Tx ring resource won't be used by other threads
1779 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1781 if (TxRingBitmap.field.Ac0DmaDone)
1782 bReschedule = RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BE);
1784 if (TxRingBitmap.field.HccaDmaDone)
1785 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_HCCA);
1787 if (TxRingBitmap.field.Ac3DmaDone)
1788 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VO);
1790 if (TxRingBitmap.field.Ac2DmaDone)
1791 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VI);
1793 if (TxRingBitmap.field.Ac1DmaDone)
1794 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BK);
1796 // Make sure to release Tx ring resource
1797 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1799 // Dequeue outgoing frames from TxSwQueue[] and process it
1800 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1807 ========================================================================
1809 Routine Description:
1810 Process MGMT ring DMA done interrupt, running in DPC level
1813 pAd Pointer to our adapter
1818 IRQL = DISPATCH_LEVEL
1822 ========================================================================
1824 VOID RTMPHandleMgmtRingDmaDoneInterrupt(
1825 IN PRTMP_ADAPTER pAd)
1828 PNDIS_PACKET pPacket;
1830 PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing;
1832 NdisAcquireSpinLock(&pAd->MgmtRingLock);
1834 RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pMgmtRing->TxDmaIdx);
1835 while (pMgmtRing->TxSwFreeIdx!= pMgmtRing->TxDmaIdx)
1838 pTxD = (PTXD_STRUC) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa);
1840 pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket;
1845 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
1846 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1848 pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket = NULL;
1850 pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket;
1853 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
1854 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1856 pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket = NULL;
1857 INC_RING_INDEX(pMgmtRing->TxSwFreeIdx, MGMT_RING_SIZE);
1859 NdisReleaseSpinLock(&pAd->MgmtRingLock);
1865 ========================================================================
1867 Routine Description:
1869 Adapter Pointer to our adapter. Dequeue all power safe delayed braodcast frames after beacon.
1871 IRQL = DISPATCH_LEVEL
1873 ========================================================================
1875 VOID RTMPHandleTBTTInterrupt(
1876 IN PRTMP_ADAPTER pAd)
1879 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1887 ========================================================================
1889 Routine Description:
1891 Adapter Pointer to our adapter. Rewrite beacon content before next send-out.
1893 IRQL = DISPATCH_LEVEL
1895 ========================================================================
1897 VOID RTMPHandlePreTBTTInterrupt(
1898 IN PRTMP_ADAPTER pAd)
1901 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1903 DBGPRINT(RT_DEBUG_TRACE, ("RTMPHandlePreTBTTInterrupt...\n"));
1910 VOID RTMPHandleRxCoherentInterrupt(
1911 IN PRTMP_ADAPTER pAd)
1913 WPDMA_GLO_CFG_STRUC GloCfg;
1917 DBGPRINT(RT_DEBUG_TRACE, ("====> pAd is NULL, return.\n"));
1921 DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPHandleRxCoherentInterrupt \n"));
1923 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG , &GloCfg.word);
1925 GloCfg.field.EnTXWriteBackDDONE = 0;
1926 GloCfg.field.EnableRxDMA = 0;
1927 GloCfg.field.EnableTxDMA = 0;
1928 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
1930 RTMPRingCleanUp(pAd, QID_AC_BE);
1931 RTMPRingCleanUp(pAd, QID_AC_BK);
1932 RTMPRingCleanUp(pAd, QID_AC_VI);
1933 RTMPRingCleanUp(pAd, QID_AC_VO);
1934 RTMPRingCleanUp(pAd, QID_HCCA);
1935 RTMPRingCleanUp(pAd, QID_MGMT);
1936 RTMPRingCleanUp(pAd, QID_RX);
1938 RTMPEnableRxTx(pAd);
1940 DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPHandleRxCoherentInterrupt \n"));
1944 VOID DBGPRINT_TX_RING(
1945 IN PRTMP_ADAPTER pAd,
1949 UINT32 Ac0HwIdx = 0, Ac0SwIdx = 0, AC0freeIdx;
1953 DBGPRINT_RAW(RT_DEBUG_TRACE, ("=====================================================\n " ));
1957 RTMP_IO_READ32(pAd, TX_BASE_PTR0, &Ac0Base);
1958 RTMP_IO_READ32(pAd, TX_CTX_IDX0, &Ac0SwIdx);
1959 RTMP_IO_READ32(pAd, TX_DTX_IDX0, &Ac0HwIdx);
1960 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_BE DESCRIPTOR \n " ));
1961 for (i=0;i<TX_RING_SIZE;i++)
1963 ptemp= (PULONG)pAd->TxRing[QID_AC_BE].Cell[i].AllocVa;
1964 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
1966 DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
1969 RTMP_IO_READ32(pAd, TX_BASE_PTR1, &Ac0Base);
1970 RTMP_IO_READ32(pAd, TX_CTX_IDX1, &Ac0SwIdx);
1971 RTMP_IO_READ32(pAd, TX_DTX_IDX1, &Ac0HwIdx);
1972 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_BK DESCRIPTOR \n " ));
1973 for (i=0;i<TX_RING_SIZE;i++)
1975 ptemp= (PULONG)pAd->TxRing[QID_AC_BK].Cell[i].AllocVa;
1976 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
1978 DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
1981 RTMP_IO_READ32(pAd, TX_BASE_PTR2, &Ac0Base);
1982 RTMP_IO_READ32(pAd, TX_CTX_IDX2, &Ac0SwIdx);
1983 RTMP_IO_READ32(pAd, TX_DTX_IDX2, &Ac0HwIdx);
1984 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_VI DESCRIPTOR \n " ));
1985 for (i=0;i<TX_RING_SIZE;i++)
1987 ptemp= (PULONG)pAd->TxRing[QID_AC_VI].Cell[i].AllocVa;
1988 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
1990 DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
1993 RTMP_IO_READ32(pAd, TX_BASE_PTR3, &Ac0Base);
1994 RTMP_IO_READ32(pAd, TX_CTX_IDX3, &Ac0SwIdx);
1995 RTMP_IO_READ32(pAd, TX_DTX_IDX3, &Ac0HwIdx);
1996 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_VO DESCRIPTOR \n " ));
1997 for (i=0;i<TX_RING_SIZE;i++)
1999 ptemp= (PULONG)pAd->TxRing[QID_AC_VO].Cell[i].AllocVa;
2000 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
2002 DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
2005 RTMP_IO_READ32(pAd, TX_BASE_PTR5, &Ac0Base);
2006 RTMP_IO_READ32(pAd, TX_CTX_IDX5, &Ac0SwIdx);
2007 RTMP_IO_READ32(pAd, TX_DTX_IDX5, &Ac0HwIdx);
2008 DBGPRINT_RAW(RT_DEBUG_TRACE, (" All QID_MGMT DESCRIPTOR \n " ));
2009 for (i=0;i<MGMT_RING_SIZE;i++)
2011 ptemp= (PULONG)pAd->MgmtRing.Cell[i].AllocVa;
2012 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
2014 DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
2018 DBGPRINT_ERR(("DBGPRINT_TX_RING(Ring %d) not supported\n", QueIdx));
2021 AC0freeIdx = pAd->TxRing[QueIdx].TxSwFreeIdx;
2023 DBGPRINT(RT_DEBUG_TRACE,("TxRing%d, TX_DTX_IDX=%d, TX_CTX_IDX=%d\n", QueIdx, Ac0HwIdx, Ac0SwIdx));
2024 DBGPRINT_RAW(RT_DEBUG_TRACE,(" TxSwFreeIdx[%d]", AC0freeIdx));
2025 DBGPRINT_RAW(RT_DEBUG_TRACE,(" pending-NDIS=%ld\n", pAd->RalinkCounters.PendingNdisPacketCount));
2031 VOID DBGPRINT_RX_RING(
2032 IN PRTMP_ADAPTER pAd)
2035 UINT32 Ac0HwIdx = 0, Ac0SwIdx = 0, AC0freeIdx;
2039 DBGPRINT_RAW(RT_DEBUG_TRACE, ("=====================================================\n " ));
2040 RTMP_IO_READ32(pAd, RX_BASE_PTR, &Ac0Base);
2041 RTMP_IO_READ32(pAd, RX_CRX_IDX, &Ac0SwIdx);
2042 RTMP_IO_READ32(pAd, RX_DRX_IDX, &Ac0HwIdx);
2043 AC0freeIdx = pAd->RxRing.RxSwReadIdx;
2045 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All RX DSP \n " ));
2046 for (i=0;i<RX_RING_SIZE;i++)
2048 ptemp = (UINT32 *)pAd->RxRing.Cell[i].AllocVa;
2049 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08x: %08x: %08x: %08x\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
2051 DBGPRINT(RT_DEBUG_TRACE,("RxRing, RX_DRX_IDX=%d, RX_CRX_IDX=%d \n", Ac0HwIdx, Ac0SwIdx));
2052 DBGPRINT_RAW(RT_DEBUG_TRACE,(" RxSwReadIdx [%d]=", AC0freeIdx));
2053 DBGPRINT_RAW(RT_DEBUG_TRACE,(" pending-NDIS=%ld\n", pAd->RalinkCounters.PendingNdisPacketCount));
2057 ========================================================================
2059 Routine Description:
2060 Suspend MSDU transmission
2063 pAd Pointer to our adapter
2070 ========================================================================
2072 VOID RTMPSuspendMsduTransmission(
2073 IN PRTMP_ADAPTER pAd)
2075 DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n"));
2079 // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
2080 // use Lowbound as R66 value on ScanNextChannel(...)
2082 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue);
2084 // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)
2085 RTMPSetAGCInitValue(pAd, BW_20);
2087 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
2092 ========================================================================
2094 Routine Description:
2095 Resume MSDU transmission
2098 pAd Pointer to our adapter
2103 IRQL = DISPATCH_LEVEL
2107 ========================================================================
2109 VOID RTMPResumeMsduTransmission(
2110 IN PRTMP_ADAPTER pAd)
2112 DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
2115 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue);
2117 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
2118 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
2122 UINT deaggregate_AMSDU_announce(
2123 IN PRTMP_ADAPTER pAd,
2124 PNDIS_PACKET pPacket,
2129 USHORT SubFrameSize;
2130 PHEADER_802_3 pAMSDUsubheader;
2132 UCHAR Header802_3[14];
2134 PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP;
2135 PNDIS_PACKET pClonePacket;
2141 while (DataSize > LENGTH_802_3)
2146 pAMSDUsubheader = (PHEADER_802_3)pData;
2147 PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8);
2148 SubFrameSize = PayloadSize + LENGTH_802_3;
2151 if ((DataSize < SubFrameSize) || (PayloadSize > 1518 ))
2156 pPayload = pData + LENGTH_802_3;
2158 pSA = pData + MAC_ADDR_LEN;
2160 // convert to 802.3 header
2161 CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP);
2163 if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) )
2165 // avoid local heap overflow, use dyanamic allocation
2166 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
2167 memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize);
2168 Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize;
2169 WpaEAPOLKeyAction(pAd, Elem);
2173 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2175 if (pRemovedLLCSNAP)
2177 pPayload -= LENGTH_802_3;
2178 PayloadSize += LENGTH_802_3;
2179 NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3);
2183 pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
2186 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2187 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket));
2191 // A-MSDU has padding to multiple of 4 including subframe header.
2192 // align SubFrameSize up to multiple of 4
2193 SubFrameSize = (SubFrameSize+3)&(~0x3);
2196 if (SubFrameSize > 1528 || SubFrameSize < 32)
2201 if (DataSize > SubFrameSize)
2203 pData += SubFrameSize;
2204 DataSize -= SubFrameSize;
2213 // finally release original rx packet
2214 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
2220 UINT BA_Reorder_AMSDU_Annnounce(
2221 IN PRTMP_ADAPTER pAd,
2222 IN PNDIS_PACKET pPacket)
2228 pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
2229 DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
2231 nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
2238 ==========================================================================
2240 Look up the MAC address in the MAC table. Return NULL if not found.
2242 pEntry - pointer to the MAC entry; NULL is not found
2243 ==========================================================================
2245 MAC_TABLE_ENTRY *MacTableLookup(
2246 IN PRTMP_ADAPTER pAd,
2250 MAC_TABLE_ENTRY *pEntry = NULL;
2252 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
2253 pEntry = pAd->MacTab.Hash[HashIdx];
2255 while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh))
2257 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
2262 pEntry = pEntry->pNext;
2268 MAC_TABLE_ENTRY *MacTableInsertEntry(
2269 IN PRTMP_ADAPTER pAd,
2272 IN BOOLEAN CleanAll)
2276 MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
2279 if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
2284 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2286 if (pAd->StaCfg.BssType == BSS_INFRA)
2289 // allocate one MAC entry
2290 NdisAcquireSpinLock(&pAd->MacTabLock);
2291 for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++) // skip entry#0 so that "entry index == AID" for fast lookup
2293 // pick up the first available vacancy
2294 if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
2295 (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
2296 (pAd->MacTab.Content[i].ValidAsApCli== FALSE) &&
2297 (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
2300 pEntry = &pAd->MacTab.Content[i];
2301 if (CleanAll == TRUE)
2303 pEntry->MaxSupportedRate = RATE_11;
2304 pEntry->CurrTxRate = RATE_11;
2305 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
2306 pEntry->PairwiseKey.KeyLen = 0;
2307 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
2310 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2312 pEntry->ValidAsCLI = TRUE;
2313 pEntry->ValidAsWDS = FALSE;
2314 pEntry->ValidAsApCli = FALSE;
2315 pEntry->ValidAsMesh = FALSE;
2316 pEntry->ValidAsDls = FALSE;
2320 pEntry->bIAmBadAtheros = FALSE;
2322 pEntry->CMTimerRunning = FALSE;
2323 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
2324 pEntry->RSNIE_Len = 0;
2325 NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
2326 pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
2328 if (pEntry->ValidAsMesh)
2329 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH);
2330 else if (pEntry->ValidAsApCli)
2331 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI);
2332 else if (pEntry->ValidAsWDS)
2333 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS);
2335 pEntry->apidx = apidx;
2338 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2340 pEntry->AuthMode = pAd->StaCfg.AuthMode;
2341 pEntry->WepStatus = pAd->StaCfg.WepStatus;
2342 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
2343 AsicRemovePairwiseKeyEntry(pAd, pEntry->apidx, (UCHAR)i);
2347 pEntry->GTKState = REKEY_NEGOTIATING;
2348 pEntry->PairwiseKey.KeyLen = 0;
2349 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
2351 if ((pAd->OpMode == OPMODE_STA) &&
2352 (pAd->StaCfg.BssType == BSS_ADHOC))
2353 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
2355 pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
2357 pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
2358 COPY_MAC_ADDR(pEntry->Addr, pAddr);
2359 pEntry->Sst = SST_NOT_AUTH;
2360 pEntry->AuthState = AS_NOT_AUTH;
2361 pEntry->Aid = (USHORT)i; //0;
2362 pEntry->CapabilityInfo = 0;
2363 pEntry->PsMode = PWR_ACTIVE;
2364 pEntry->PsQIdleCount = 0;
2365 pEntry->NoDataIdleCount = 0;
2366 pEntry->ContinueTxFailCnt = 0;
2367 InitializeQueueHeader(&pEntry->PsQueue);
2370 pAd->MacTab.Size ++;
2371 // Add this entry into ASIC RX WCID search table
2372 RT28XX_STA_ENTRY_ADD(pAd, pEntry);
2376 DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size));
2381 // add this MAC entry into HASH table
2384 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
2385 if (pAd->MacTab.Hash[HashIdx] == NULL)
2387 pAd->MacTab.Hash[HashIdx] = pEntry;
2391 pCurrEntry = pAd->MacTab.Hash[HashIdx];
2392 while (pCurrEntry->pNext != NULL)
2393 pCurrEntry = pCurrEntry->pNext;
2394 pCurrEntry->pNext = pEntry;
2398 NdisReleaseSpinLock(&pAd->MacTabLock);
2403 ==========================================================================
2405 Delete a specified client from MAC table
2406 ==========================================================================
2408 BOOLEAN MacTableDeleteEntry(
2409 IN PRTMP_ADAPTER pAd,
2414 MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
2417 if (wcid >= MAX_LEN_OF_MAC_TABLE)
2420 NdisAcquireSpinLock(&pAd->MacTabLock);
2422 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
2423 pEntry = &pAd->MacTab.Content[wcid];
2425 if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh
2428 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
2431 // Delete this entry from ASIC on-chip WCID Table
2432 RT28XX_STA_ENTRY_MAC_RESET(pAd, wcid);
2434 #ifdef DOT11_N_SUPPORT
2435 // free resources of BA
2436 BASessionTearDownALL(pAd, pEntry->Aid);
2437 #endif // DOT11_N_SUPPORT //
2441 pProbeEntry = pAd->MacTab.Hash[HashIdx];
2442 ASSERT(pProbeEntry);
2447 if (pProbeEntry == pEntry)
2449 if (pPrevEntry == NULL)
2451 pAd->MacTab.Hash[HashIdx] = pEntry->pNext;
2455 pPrevEntry->pNext = pEntry->pNext;
2460 pPrevEntry = pProbeEntry;
2461 pProbeEntry = pProbeEntry->pNext;
2462 } while (pProbeEntry);
2465 ASSERT(pProbeEntry != NULL);
2467 RT28XX_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
2470 if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
2472 RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
2473 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
2477 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
2478 pAd->MacTab.Size --;
2479 DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size));
2483 printk("\n%s: Impossible Wcid = %d !!!!!\n", __func__, wcid);
2487 NdisReleaseSpinLock(&pAd->MacTabLock);
2489 //Reset operating mode when no Sta.
2490 if (pAd->MacTab.Size == 0)
2492 #ifdef DOT11_N_SUPPORT
2493 pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
2494 #endif // DOT11_N_SUPPORT //
2495 AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/);
2503 ==========================================================================
2505 This routine reset the entire MAC table. All packets pending in
2506 the power-saving queues are freed here.
2507 ==========================================================================
2510 IN PRTMP_ADAPTER pAd)
2514 DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
2515 //NdisAcquireSpinLock(&pAd->MacTabLock);
2517 for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
2519 RT28XX_STA_ENTRY_MAC_RESET(pAd, i);
2520 if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
2523 #ifdef DOT11_N_SUPPORT
2524 // free resources of BA
2525 BASessionTearDownALL(pAd, i);
2526 #endif // DOT11_N_SUPPORT //
2528 pAd->MacTab.Content[i].ValidAsCLI = FALSE;
2533 //AsicDelWcidTab(pAd, i);
2541 ==========================================================================
2544 IRQL = DISPATCH_LEVEL
2546 ==========================================================================
2549 IN PRTMP_ADAPTER pAd,
2550 IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
2552 IN USHORT CapabilityInfo,
2554 IN USHORT ListenIntv)
2556 COPY_MAC_ADDR(AssocReq->Addr, pAddr);
2557 // Add mask to support 802.11b mode only
2558 AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request
2559 AssocReq->Timeout = Timeout;
2560 AssocReq->ListenIntv = ListenIntv;
2565 ==========================================================================
2568 IRQL = DISPATCH_LEVEL
2570 ==========================================================================
2572 VOID DisassocParmFill(
2573 IN PRTMP_ADAPTER pAd,
2574 IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
2578 COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
2579 DisassocReq->Reason = Reason;
2584 ========================================================================
2586 Routine Description:
2587 Check the out going frame, if this is an DHCP or ARP datagram
2588 will be duplicate another frame at low data rate transmit.
2591 pAd Pointer to our adapter
2592 pPacket Pointer to outgoing Ndis frame
2595 TRUE To be duplicate at Low data rate transmit. (1mb)
2598 IRQL = DISPATCH_LEVEL
2602 MAC header + IP Header + UDP Header
2606 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
2608 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
2611 port 0x43 means Bootstrap Protocol, server.
2612 Port 0x44 means Bootstrap Protocol, client.
2614 ========================================================================
2617 BOOLEAN RTMPCheckDHCPFrame(
2618 IN PRTMP_ADAPTER pAd,
2619 IN PNDIS_PACKET pPacket)
2621 PACKET_INFO PacketInfo;
2622 ULONG NumberOfBytesRead = 0;
2623 ULONG CurrentOffset = 0;
2624 PVOID pVirtualAddress = NULL;
2625 UINT NdisBufferLength;
2628 UCHAR ByteOffset36 = 0;
2629 UCHAR ByteOffset38 = 0;
2630 BOOLEAN ReadFirstParm = TRUE;
2632 RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength);
2634 NumberOfBytesRead += NdisBufferLength;
2635 pSrc = (PUCHAR) pVirtualAddress;
2636 Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
2639 // Check DHCP & BOOTP protocol
2641 while (NumberOfBytesRead <= PacketInfo.TotalPacketLength)
2643 if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE))
2645 CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength);
2646 ByteOffset36 = *(pSrc + CurrentOffset);
2647 ReadFirstParm = FALSE;
2650 if (NumberOfBytesRead >= 37)
2652 CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength);
2653 ByteOffset38 = *(pSrc + CurrentOffset);
2660 // Check for DHCP & BOOTP protocol
2661 if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43))
2664 // 2054 (hex 0806) for ARP datagrams
2665 // if this packet is not ARP datagrams, then do nothing
2666 // ARP datagrams will also be duplicate at 1mb broadcast frames
2668 if (Protocol != 0x0806 )
2676 BOOLEAN RTMPCheckEtherType(
2677 IN PRTMP_ADAPTER pAd,
2678 IN PNDIS_PACKET pPacket)
2684 UINT16 srcPort, dstPort;
2685 BOOLEAN status = TRUE;
2688 pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
2689 pktLen = GET_OS_PKT_LEN(pPacket);
2693 RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
2695 // get Ethernet protocol field
2696 TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13];
2698 pSrcBuf += LENGTH_802_3; // Skip the Ethernet Header.
2700 if (TypeLen <= 1500)
2701 { // 802.3, 802.3 LLC
2703 DestMAC(6) + SrcMAC(6) + Lenght(2) +
2704 DSAP(1) + SSAP(1) + Control(1) +
2705 if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
2706 => + SNAP (5, OriginationID(3) + etherType(2))
2708 if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03)
2710 Sniff2BytesFromNdisBuffer(pSrcBuf, 6, &Byte0, &Byte1);
2711 RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
2712 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2713 pSrcBuf += 8; // Skip this LLC/SNAP header
2717 //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.
2721 // If it's a VLAN packet, get the real Type/Length field.
2722 if (TypeLen == 0x8100)
2724 /* 0x8100 means VLAN packets */
2726 /* Dest. MAC Address (6-bytes) +
2727 Source MAC Address (6-bytes) +
2728 Length/Type = 802.1Q Tag Type (2-byte) +
2729 Tag Control Information (2-bytes) +
2730 Length / Type (2-bytes) +
2731 data payload (0-n bytes) +
2733 Frame Check Sequence (4-bytes) */
2735 RTMP_SET_PACKET_VLAN(pPacket, 1);
2736 Sniff2BytesFromNdisBuffer(pSrcBuf, 2, &Byte0, &Byte1);
2737 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2739 pSrcBuf += 4; // Skip the VLAN Header.
2746 ASSERT((pktLen > 34));
2747 if (*(pSrcBuf + 9) == 0x11)
2749 ASSERT((pktLen > 34)); // 14 for ethernet header, 20 for IP header
2751 pSrcBuf += 20; // Skip the IP header
2752 srcPort = OS_NTOHS(*((UINT16 *)pSrcBuf));
2753 dstPort = OS_NTOHS(*((UINT16 *)(pSrcBuf +2)));
2755 if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44))
2756 { //It's a BOOTP/DHCP packet
2757 RTMP_SET_PACKET_DHCP(pPacket, 1);
2765 RTMP_SET_PACKET_DHCP(pPacket, 1);
2771 RTMP_SET_PACKET_EAPOL(pPacket, 1);
2785 VOID Update_Rssi_Sample(
2786 IN PRTMP_ADAPTER pAd,
2787 IN RSSI_SAMPLE *pRssi,
2788 IN PRXWI_STRUC pRxWI)
2790 CHAR rssi0 = pRxWI->RSSI0;
2791 CHAR rssi1 = pRxWI->RSSI1;
2792 CHAR rssi2 = pRxWI->RSSI2;
2796 pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0);
2797 pRssi->AvgRssi0X8 = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
2798 pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
2803 pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1);
2804 pRssi->AvgRssi1X8 = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
2805 pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
2810 pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2);
2811 pRssi->AvgRssi2X8 = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
2812 pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
2818 // Normal legacy Rx packet indication
2819 VOID Indicate_Legacy_Packet(
2820 IN PRTMP_ADAPTER pAd,
2822 IN UCHAR FromWhichBSSID)
2824 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2825 UCHAR Header802_3[LENGTH_802_3];
2827 // 1. get 802.3 Header
2829 // a. pointer pRxBlk->pData to payload
2830 // b. modify pRxBlk->DataSize
2831 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2832 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2834 if (pRxBlk->DataSize > MAX_RX_PKT_LEN)
2838 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2843 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
2846 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2849 // pass this 802.3 packet to upper layer or forward this packet to WM directly
2851 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2852 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
2856 // Normal, AMPDU or AMSDU
2857 VOID CmmRxnonRalinkFrameIndicate(
2858 IN PRTMP_ADAPTER pAd,
2860 IN UCHAR FromWhichBSSID)
2862 #ifdef DOT11_N_SUPPORT
2863 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
2865 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2868 #endif // DOT11_N_SUPPORT //
2870 #ifdef DOT11_N_SUPPORT
2871 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
2874 Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2877 #endif // DOT11_N_SUPPORT //
2879 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
2885 VOID CmmRxRalinkFrameIndicate(
2886 IN PRTMP_ADAPTER pAd,
2887 IN MAC_TABLE_ENTRY *pEntry,
2889 IN UCHAR FromWhichBSSID)
2891 UCHAR Header802_3[LENGTH_802_3];
2893 UINT16 Payload1Size, Payload2Size;
2895 PNDIS_PACKET pPacket2 = NULL;
2899 Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8);
2901 if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize))
2903 /* skip two byte MSDU2 len */
2905 pRxBlk->DataSize -= 2;
2910 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2914 // get 802.3 Header and remove LLC
2915 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2916 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2918 ASSERT(pRxBlk->pRxPacket);
2920 // Ralink Aggregation frame
2921 pAd->RalinkCounters.OneSecRxAggregationCount ++;
2922 Payload1Size = pRxBlk->DataSize - Msdu2Size;
2923 Payload2Size = Msdu2Size - LENGTH_802_3;
2925 pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
2927 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2928 pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID);
2933 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2937 // update payload size of 1st packet
2938 pRxBlk->DataSize = Payload1Size;
2939 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2941 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2942 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID);
2946 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2947 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
2952 #define RESET_FRAGFRAME(_fragFrame) \
2954 _fragFrame.RxSize = 0; \
2955 _fragFrame.Sequence = 0; \
2956 _fragFrame.LastFrag = 0; \
2957 _fragFrame.Flags = 0; \
2961 PNDIS_PACKET RTMPDeFragmentDataFrame(
2962 IN PRTMP_ADAPTER pAd,
2965 PHEADER_802_11 pHeader = pRxBlk->pHeader;
2966 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2967 UCHAR *pData = pRxBlk->pData;
2968 USHORT DataSize = pRxBlk->DataSize;
2969 PNDIS_PACKET pRetPacket = NULL;
2970 UCHAR *pFragBuffer = NULL;
2971 BOOLEAN bReassDone = FALSE;
2972 UCHAR HeaderRoom = 0;
2977 HeaderRoom = pData - (UCHAR *)pHeader;
2979 // Re-assemble the fragmented packets
2980 if (pHeader->Frag == 0) // Frag. Number is 0 : First frag or only one pkt
2982 // the first pkt of fragment, record it.
2983 if (pHeader->FC.MoreFrag)
2985 ASSERT(pAd->FragFrame.pFragPacket);
2986 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2987 pAd->FragFrame.RxSize = DataSize + HeaderRoom;
2988 NdisMoveMemory(pFragBuffer, pHeader, pAd->FragFrame.RxSize);
2989 pAd->FragFrame.Sequence = pHeader->Sequence;
2990 pAd->FragFrame.LastFrag = pHeader->Frag; // Should be 0
2991 ASSERT(pAd->FragFrame.LastFrag == 0);
2992 goto done; // end of processing this frame
2995 else //Middle & End of fragment
2997 if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
2998 (pHeader->Frag != (pAd->FragFrame.LastFrag + 1)))
3000 // Fragment is not the same sequence or out of fragment number order
3001 // Reset Fragment control blk
3002 RESET_FRAGFRAME(pAd->FragFrame);
3003 DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n"));
3004 goto done; // give up this frame
3006 else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE)
3008 // Fragment frame is too large, it exeeds the maximum frame size.
3009 // Reset Fragment control blk
3010 RESET_FRAGFRAME(pAd->FragFrame);
3011 DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
3012 goto done; // give up this frame
3016 // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.
3017 // In this case, we will dropt it.
3019 if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H)))
3021 DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag));
3022 goto done; // give up this frame
3025 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
3027 // concatenate this fragment into the re-assembly buffer
3028 NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize);
3029 pAd->FragFrame.RxSize += DataSize;
3030 pAd->FragFrame.LastFrag = pHeader->Frag; // Update fragment number
3033 if (pHeader->FC.MoreFrag == FALSE)
3040 // always release rx fragmented packet
3041 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
3043 // return defragmented packet if packet is reassembled completely
3044 // otherwise return NULL
3047 PNDIS_PACKET pNewFragPacket;
3049 // allocate a new packet buffer for fragment
3050 pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
3054 pRetPacket = pAd->FragFrame.pFragPacket;
3055 pAd->FragFrame.pFragPacket = pNewFragPacket;
3056 pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
3057 pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom;
3058 pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
3059 pRxBlk->pRxPacket = pRetPacket;
3063 RESET_FRAGFRAME(pAd->FragFrame);
3071 VOID Indicate_AMSDU_Packet(
3072 IN PRTMP_ADAPTER pAd,
3074 IN UCHAR FromWhichBSSID)
3078 update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
3079 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
3080 nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize);
3083 VOID Indicate_EAPOL_Packet(
3084 IN PRTMP_ADAPTER pAd,
3086 IN UCHAR FromWhichBSSID)
3088 MAC_TABLE_ENTRY *pEntry = NULL;
3090 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3092 pEntry = &pAd->MacTab.Content[BSSID_WCID];
3093 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
3099 DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
3101 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
3106 #define BCN_TBTT_OFFSET 64 //defer 64 us
3107 VOID ReSyncBeaconTime(
3108 IN PRTMP_ADAPTER pAd)
3114 Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
3116 pAd->TbttTickCount++;
3119 // The updated BeaconInterval Value will affect Beacon Interval after two TBTT
3120 // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
3122 if (Offset == (BCN_TBTT_OFFSET-2))
3124 BCN_TIME_CFG_STRUC csr;
3125 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
3126 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; // ASIC register in units of 1/16 TU = 64us
3127 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
3131 if (Offset == (BCN_TBTT_OFFSET-1))
3133 BCN_TIME_CFG_STRUC csr;
3135 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
3136 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU
3137 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);