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 || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED
540 if (pAd->LatchRfRegs.Channel > 14)
541 pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
543 pAd->CommonCfg.MlmeTransmit.field.MODE = 0;
548 // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
549 // Snice it's been set to 0 while on MgtMacHeaderInit
550 // By the way this will cause frame to be send on PWR_SAVE failed.
552 // pHeader_802_11->FC.PwrMgmt = 0; // (pAd->StaCfg.Psm == PWR_SAVE);
554 // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
556 // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
557 if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL))
559 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
560 (pHeader_802_11->FC.SubType == SUBTYPE_ACTION))
561 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
563 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
566 bInsertTimestamp = FALSE;
567 if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
569 //Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue.
570 if ((pAd->OpMode == OPMODE_STA) && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL))
572 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
574 bAckRequired = FALSE;
576 else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
578 if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
580 bAckRequired = FALSE;
581 pHeader_802_11->Duration = 0;
586 pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
587 if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
589 bInsertTimestamp = TRUE;
594 pHeader_802_11->Sequence = pAd->Sequence++;
595 if (pAd->Sequence >0xfff)
598 // Before radar detection done, mgmt frame can not be sent but probe req
599 // Because we need to use probe req to trigger driver to send probe req in passive scan
600 if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
601 && (pAd->CommonCfg.bIEEE80211H == 1)
602 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
604 DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
605 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
606 return (NDIS_STATUS_FAILURE);
610 // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
611 // should always has only one ohysical buffer, and the whole frame size equals
612 // to the first scatter buffer size
615 // Initialize TX Descriptor
616 // For inter-frame gap, the number is for this frame and next frame
617 // For MLME rate, we will fix as 2Mb to match other vendor's implement
619 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
620 if (pMacEntry == NULL)
622 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
623 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
627 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
628 bInsertTimestamp, FALSE, bAckRequired, FALSE,
629 0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE),
630 pMacEntry->MaxHTPhyMode.field.MCS, 0,
631 (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
632 IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
635 // Now do hardware-depened kick out.
636 HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen);
638 // Make sure to release MGMT ring resource
639 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
640 return NDIS_STATUS_SUCCESS;
644 /********************************************************************************
646 New DeQueue Procedures.
648 ********************************************************************************/
650 #define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \
652 if (bIntContext == FALSE) \
653 RTMP_IRQ_LOCK((lock), IrqFlags); \
656 #define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \
658 if (bIntContext == FALSE) \
659 RTMP_IRQ_UNLOCK((lock), IrqFlags); \
663 ========================================================================
664 Tx Path design algorithm:
665 Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal),
666 Specific Packet Type. Following show the classification rule and policy for each kinds of packets.
667 Classification Rule=>
668 Multicast: (*addr1 & 0x01) == 0x01
669 Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc.
670 11N Rate : If peer support HT
671 (1).AMPDU -- If TXBA is negotiated.
672 (2).AMSDU -- If AMSDU is capable for both peer and ourself.
673 *). AMSDU can embedded in a AMPDU, but now we didn't support it.
674 (3).Normal -- Other packets which send as 11n rate.
676 B/G Rate : If peer is b/g only.
677 (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6
678 (2).Normal -- Other packets which send as b/g rate.
680 The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
682 Classified Packet Handle Rule=>
684 No ACK, //pTxBlk->bAckRequired = FALSE;
685 No WMM, //pTxBlk->bWMM = FALSE;
686 No piggyback, //pTxBlk->bPiggyBack = FALSE;
687 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
688 Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use
689 the same policy to handle it.
690 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
693 No piggyback, //pTxBlk->bPiggyBack = FALSE;
705 ========================================================================
707 static UCHAR TxPktClassification(
708 IN RTMP_ADAPTER *pAd,
709 IN PNDIS_PACKET pPacket)
711 UCHAR TxFrameType = TX_UNKOWN_FRAME;
713 MAC_TABLE_ENTRY *pMacEntry = NULL;
714 BOOLEAN bHTRate = FALSE;
716 Wcid = RTMP_GET_PACKET_WCID(pPacket);
717 if (Wcid == MCAST_WCID)
718 { // Handle for RA is Broadcast/Multicast Address.
719 return TX_MCAST_FRAME;
722 // Handle for unicast packets
723 pMacEntry = &pAd->MacTab.Content[Wcid];
724 if (RTMP_GET_PACKET_LOWRATE(pPacket))
725 { // It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame
726 TxFrameType = TX_LEGACY_FRAME;
728 else if (IS_HT_RATE(pMacEntry))
729 { // it's a 11n capable packet
731 // Depends on HTPhyMode to check if the peer support the HTRate transmission.
732 // Currently didn't support A-MSDU embedded in A-MPDU
734 if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE))
735 TxFrameType = TX_LEGACY_FRAME;
736 #ifdef UAPSD_AP_SUPPORT
737 else if (RTMP_GET_PACKET_EOSP(pPacket))
738 TxFrameType = TX_LEGACY_FRAME;
739 #endif // UAPSD_AP_SUPPORT //
740 else if((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0)
741 return TX_AMPDU_FRAME;
742 else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED))
743 return TX_AMSDU_FRAME;
745 TxFrameType = TX_LEGACY_FRAME;
748 { // it's a legacy b/g packet.
749 if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) &&
750 (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) &&
751 (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
752 { // if peer support Ralink Aggregation, we use it.
753 TxFrameType = TX_RALINK_FRAME;
757 TxFrameType = TX_LEGACY_FRAME;
761 // Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU.
762 if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) && (TxFrameType == TX_LEGACY_FRAME))
763 TxFrameType = TX_FRAG_FRAME;
769 BOOLEAN RTMP_FillTxBlkInfo(
770 IN RTMP_ADAPTER *pAd,
773 PACKET_INFO PacketInfo;
774 PNDIS_PACKET pPacket;
775 PMAC_TABLE_ENTRY pMacEntry = NULL;
777 pPacket = pTxBlk->pPacket;
778 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
780 pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket);
781 pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket);
782 pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket);
783 pTxBlk->FrameGap = IFS_HTTXOP; // ASIC determine Frame Gap
785 if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket))
786 TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame);
788 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame);
790 // Default to clear this flag
791 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS);
794 if (pTxBlk->Wcid == MCAST_WCID)
796 pTxBlk->pMacEntry = NULL;
798 #ifdef MCAST_RATE_SPECIFIC
799 PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket);
800 if (((*pDA & 0x01) == 0x01) && (*pDA != 0xff))
801 pTxBlk->pTransmit = &pAd->CommonCfg.MCastPhyMode;
803 #endif // MCAST_RATE_SPECIFIC //
804 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
807 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); // AckRequired = FALSE, when broadcast packet in Adhoc mode.
808 //TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate);
809 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag);
810 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
811 if (RTMP_GET_PACKET_MOREDATA(pPacket))
813 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
819 pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
820 pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode;
822 pMacEntry = pTxBlk->pMacEntry;
825 // For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK.
826 if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK)
827 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
829 TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired);
832 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
835 // If support WMM, enable it.
836 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
837 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM);
841 if (pTxBlk->TxFrameType == TX_LEGACY_FRAME)
843 if ( (RTMP_GET_PACKET_LOWRATE(pPacket)) ||
844 ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1)))
845 { // Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate.
846 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
848 // Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it???
849 if (IS_HT_STA(pTxBlk->pMacEntry) &&
850 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) &&
851 ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)))
853 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
854 TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS);
858 if ( (IS_HT_RATE(pMacEntry) == FALSE) &&
859 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE)))
860 { // Currently piggy-back only support when peer is operate in b/g mode.
861 TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack);
864 if (RTMP_GET_PACKET_MOREDATA(pPacket))
866 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
868 #ifdef UAPSD_AP_SUPPORT
869 if (RTMP_GET_PACKET_EOSP(pPacket))
871 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP);
873 #endif // UAPSD_AP_SUPPORT //
875 else if (pTxBlk->TxFrameType == TX_FRAG_FRAME)
877 TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag);
880 pMacEntry->DebugTxCount++;
887 BOOLEAN CanDoAggregateTransmit(
888 IN RTMP_ADAPTER *pAd,
889 IN NDIS_PACKET *pPacket,
893 //printk("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType);
895 if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
898 if (RTMP_GET_PACKET_DHCP(pPacket) ||
899 RTMP_GET_PACKET_EAPOL(pPacket) ||
900 RTMP_GET_PACKET_WAI(pPacket))
903 if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) &&
904 ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100)))
905 { // For AMSDU, allow the packets with total length < max-amsdu size
909 if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) &&
910 (pTxBlk->TxPacketList.Number == 2))
911 { // For RALINK-Aggregation, allow two frames in one batch.
915 if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP
923 ========================================================================
926 To do the enqueue operation and extract the first item of waiting
927 list. If a number of available shared memory segments could meet
928 the request of extracted item, the extracted item will be fragmented
929 into shared memory segments.
932 pAd Pointer to our adapter
933 pQueue Pointer to Waiting Queue
938 IRQL = DISPATCH_LEVEL
942 ========================================================================
944 VOID RTMPDeQueuePacket(
945 IN PRTMP_ADAPTER pAd,
946 IN BOOLEAN bIntContext,
947 IN UCHAR QIdx, /* BulkOutPipeId */
948 IN UCHAR Max_Tx_Packets)
950 PQUEUE_ENTRY pEntry = NULL;
951 PNDIS_PACKET pPacket;
952 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
954 PQUEUE_HEADER pQueue;
955 ULONG FreeNumber[NUM_OF_TX_RING];
956 UCHAR QueIdx, sQIdx, eQIdx;
957 unsigned long IrqFlags = 0;
958 BOOLEAN hasTxDesc = FALSE;
964 RtmpDiagStruct *pDiagStruct = &pAd->DiagStruct;
968 if (QIdx == NUM_OF_TX_RING)
971 eQIdx = 3; // 4 ACs, start from 0.
975 sQIdx = eQIdx = QIdx;
978 for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++)
982 RT28XX_START_DEQUEUE(pAd, QueIdx, IrqFlags);
985 firstRound = ((QueIdx == 0) ? TRUE : FALSE);
986 #endif // DBG_DIAGNOSE //
990 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |
991 fRTMP_ADAPTER_RADIO_OFF |
992 fRTMP_ADAPTER_RESET_IN_PROGRESS |
993 fRTMP_ADAPTER_HALT_IN_PROGRESS |
994 fRTMP_ADAPTER_NIC_NOT_EXIST))))
996 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
1000 if (Count >= Max_Tx_Packets)
1003 DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1004 if (&pAd->TxSwQueue[QueIdx] == NULL)
1007 if (firstRound == TRUE)
1008 pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][0]++;
1009 #endif // DBG_DIAGNOSE //
1010 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1014 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
1017 if (firstRound == TRUE)
1019 UCHAR txDescNumLevel, txSwQNumLevel;
1021 txDescNumLevel = (TX_RING_SIZE - FreeNumber[QueIdx]); // Number of occupied hw desc.
1022 txDescNumLevel = ((txDescNumLevel <=15) ? txDescNumLevel : 15);
1023 pDiagStruct->TxDescCnt[pDiagStruct->ArrayCurIdx][txDescNumLevel]++;
1025 txSwQNumLevel = ((pAd->TxSwQueue[QueIdx].Number <=7) ? pAd->TxSwQueue[QueIdx].Number : 8);
1026 pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][txSwQNumLevel]++;
1030 #endif // DBG_DIAGNOSE //
1032 if (FreeNumber[QueIdx] <= 5)
1034 // free Tx(QueIdx) resources
1035 RTMPFreeTXDUponTxDmaDone(pAd, QueIdx);
1036 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
1039 // probe the Queue Head
1040 pQueue = &pAd->TxSwQueue[QueIdx];
1041 if ((pEntry = pQueue->Head) == NULL)
1043 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1048 NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK));
1049 pTxBlk->QueIdx = QueIdx;
1051 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
1053 // Early check to make sure we have enoguh Tx Resource.
1054 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
1057 pAd->PrivateInfo.TxRingFullCnt++;
1059 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1064 pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
1065 pEntry = RemoveHeadQueue(pQueue);
1066 pTxBlk->TotalFrameNum++;
1067 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
1068 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
1069 pTxBlk->pPacket = pPacket;
1070 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
1072 if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME)
1074 // Enhance SW Aggregation Mechanism
1075 if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType))
1077 InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
1078 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1083 if((pEntry = pQueue->Head) == NULL)
1086 // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation.
1087 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
1088 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
1089 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
1090 if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE))
1093 //Remove the packet from the TxSwQueue and insert into pTxBlk
1094 pEntry = RemoveHeadQueue(pQueue);
1096 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
1097 pTxBlk->TotalFrameNum++;
1098 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
1099 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
1100 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
1103 if (pTxBlk->TxPacketList.Number == 1)
1104 pTxBlk->TxFrameType = TX_LEGACY_FRAME;
1108 Count += pTxBlk->TxPacketList.Number;
1110 // Do HardTransmit now.
1111 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1112 Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
1114 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1115 // static rate also need NICUpdateFifoStaCounters() function.
1116 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
1117 NICUpdateFifoStaCounters(pAd);
1120 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
1127 ========================================================================
1129 Routine Description:
1130 Calculates the duration which is required to transmit out frames
1131 with given size and specified rate.
1134 pAd Pointer to our adapter
1136 Size Frame size in units of byte
1139 Duration number in units of usec
1141 IRQL = PASSIVE_LEVEL
1142 IRQL = DISPATCH_LEVEL
1146 ========================================================================
1148 USHORT RTMPCalcDuration(
1149 IN PRTMP_ADAPTER pAd,
1155 if (Rate < RATE_FIRST_OFDM_RATE) // CCK
1157 if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED))
1158 Duration = 96; // 72+24 preamble+plcp
1160 Duration = 192; // 144+48 preamble+plcp
1162 Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]);
1163 if ((Size << 4) % RateIdTo500Kbps[Rate])
1166 else if (Rate <= RATE_LAST_OFDM_RATE)// OFDM rates
1168 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
1169 Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
1170 if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
1175 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
1178 return (USHORT)Duration;
1183 ========================================================================
1185 Routine Description:
1186 Calculates the duration which is required to transmit out frames
1187 with given size and specified rate.
1190 pTxWI Pointer to head of each MPDU to HW.
1191 Ack Setting for Ack requirement bit
1192 Fragment Setting for Fragment bit
1193 RetryMode Setting for retry mode
1194 Ifs Setting for IFS gap
1195 Rate Setting for transmit rate
1196 Service Setting for service
1198 TxPreamble Short or Long preamble when using CCK rates
1199 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1204 IRQL = PASSIVE_LEVEL
1205 IRQL = DISPATCH_LEVEL
1207 See also : BASmartHardTransmit() !!!
1209 ========================================================================
1212 IN PRTMP_ADAPTER pAd,
1213 IN PTXWI_STRUC pOutTxWI,
1216 IN BOOLEAN InsTimestamp,
1219 IN BOOLEAN NSeq, // HW new a sequence.
1228 IN HTTRANSMIT_SETTING *pTransmit)
1230 PMAC_TABLE_ENTRY pMac = NULL;
1234 if (WCID < MAX_LEN_OF_MAC_TABLE)
1235 pMac = &pAd->MacTab.Content[WCID];
1238 // Always use Long preamble before verifiation short preamble functionality works well.
1239 // Todo: remove the following line if short preamble functionality works
1241 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1242 NdisZeroMemory(&TxWI, TXWI_SIZE);
1247 pTxWI->CFACK = CFACK;
1248 pTxWI->TS= InsTimestamp;
1249 pTxWI->AMPDU = AMPDU;
1251 pTxWI->txop= Txopmode;
1254 // John tune the performace with Intel Client in 20 MHz performance
1255 BASize = pAd->CommonCfg.TxBASize;
1259 pTxWI->BAWinSize = BASize;
1260 pTxWI->ShortGI = pTransmit->field.ShortGI;
1261 pTxWI->STBC = pTransmit->field.STBC;
1263 pTxWI->WirelessCliID = WCID;
1264 pTxWI->MPDUtotalByteCount = Length;
1265 pTxWI->PacketId = PID;
1267 // If CCK or OFDM, BW must be 20
1268 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1270 pTxWI->MCS = pTransmit->field.MCS;
1271 pTxWI->PHYMODE = pTransmit->field.MODE;
1272 pTxWI->CFACK = CfAck;
1276 if (pAd->CommonCfg.bMIMOPSEnable)
1278 if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1280 // Dynamic MIMO Power Save Mode
1283 else if (pMac->MmpsMode == MMPS_STATIC)
1285 // Static MIMO Power Save Mode
1286 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1293 //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;
1294 if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled))
1296 pTxWI->MpduDensity = 7;
1300 pTxWI->MpduDensity = pMac->MpduDensity;
1304 pTxWI->PacketId = pTxWI->MCS;
1305 NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC));
1309 VOID RTMPWriteTxWI_Data(
1310 IN PRTMP_ADAPTER pAd,
1311 IN OUT PTXWI_STRUC pTxWI,
1314 HTTRANSMIT_SETTING *pTransmit;
1315 PMAC_TABLE_ENTRY pMacEntry;
1320 pTransmit = pTxBlk->pTransmit;
1321 pMacEntry = pTxBlk->pMacEntry;
1325 // Always use Long preamble before verifiation short preamble functionality works well.
1326 // Todo: remove the following line if short preamble functionality works
1328 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1329 NdisZeroMemory(pTxWI, TXWI_SIZE);
1331 pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1332 pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1333 pTxWI->txop = pTxBlk->FrameGap;
1335 pTxWI->WirelessCliID = pTxBlk->Wcid;
1337 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1338 pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
1340 // If CCK or OFDM, BW must be 20
1341 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1342 pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
1344 // John tune the performace with Intel Client in 20 MHz performance
1345 BASize = pAd->CommonCfg.TxBASize;
1346 if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry))
1348 UCHAR RABAOriIdx = 0; //The RA's BA Originator table index.
1350 RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
1351 BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1354 pTxWI->TxBF = pTransmit->field.TxBF;
1355 pTxWI->BAWinSize = BASize;
1356 pTxWI->ShortGI = pTransmit->field.ShortGI;
1357 pTxWI->STBC = pTransmit->field.STBC;
1359 pTxWI->MCS = pTransmit->field.MCS;
1360 pTxWI->PHYMODE = pTransmit->field.MODE;
1364 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1366 // Dynamic MIMO Power Save Mode
1369 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1371 // Static MIMO Power Save Mode
1372 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1379 if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled))
1381 pTxWI->MpduDensity = 7;
1385 pTxWI->MpduDensity = pMacEntry->MpduDensity;
1390 if (pTxBlk->QueIdx== 0)
1392 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1393 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1395 #endif // DBG_DIAGNOSE //
1397 // for rate adapation
1398 pTxWI->PacketId = pTxWI->MCS;
1402 VOID RTMPWriteTxWI_Cache(
1403 IN PRTMP_ADAPTER pAd,
1404 IN OUT PTXWI_STRUC pTxWI,
1407 PHTTRANSMIT_SETTING pTransmit;
1408 PMAC_TABLE_ENTRY pMacEntry;
1413 pMacEntry = pTxBlk->pMacEntry;
1414 pTransmit = pTxBlk->pTransmit;
1416 if (pMacEntry->bAutoTxRateSwitch)
1418 pTxWI->txop = IFS_HTTXOP;
1420 // If CCK or OFDM, BW must be 20
1421 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1422 pTxWI->ShortGI = pTransmit->field.ShortGI;
1423 pTxWI->STBC = pTransmit->field.STBC;
1425 pTxWI->MCS = pTransmit->field.MCS;
1426 pTxWI->PHYMODE = pTransmit->field.MODE;
1428 // set PID for TxRateSwitching
1429 pTxWI->PacketId = pTransmit->field.MCS;
1432 pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE);
1435 if (pAd->CommonCfg.bMIMOPSEnable)
1437 // MIMO Power Save Mode
1438 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1440 // Dynamic MIMO Power Save Mode
1443 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1445 // Static MIMO Power Save Mode
1446 if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7))
1455 if (pTxBlk->QueIdx== 0)
1457 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1458 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1460 #endif // DBG_DIAGNOSE //
1462 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1468 ========================================================================
1470 Routine Description:
1471 Calculates the duration which is required to transmit out frames
1472 with given size and specified rate.
1475 pTxD Pointer to transmit descriptor
1476 Ack Setting for Ack requirement bit
1477 Fragment Setting for Fragment bit
1478 RetryMode Setting for retry mode
1479 Ifs Setting for IFS gap
1480 Rate Setting for transmit rate
1481 Service Setting for service
1483 TxPreamble Short or Long preamble when using CCK rates
1484 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1489 IRQL = PASSIVE_LEVEL
1490 IRQL = DISPATCH_LEVEL
1492 ========================================================================
1494 VOID RTMPWriteTxDescriptor(
1495 IN PRTMP_ADAPTER pAd,
1501 // Always use Long preamble before verifiation short preamble functionality works well.
1502 // Todo: remove the following line if short preamble functionality works
1504 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1506 pTxD->WIV = (bWIV) ? 1: 0;
1507 pTxD->QSEL= (QueueSEL);
1508 if (pAd->bGenOneHCCA == TRUE)
1509 pTxD->QSEL= FIFO_HCCA;
1514 // should be called only when -
1515 // 1. MEADIA_CONNECTED
1516 // 2. AGGREGATION_IN_USED
1517 // 3. Fragmentation not in used
1518 // 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible
1519 BOOLEAN TxFrameIsAggregatible(
1520 IN PRTMP_ADAPTER pAd,
1521 IN PUCHAR pPrevAddr1,
1525 // can't aggregate EAPOL (802.1x) frame
1526 if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1529 // can't aggregate multicast/broadcast frame
1530 if (p8023hdr[0] & 0x01)
1533 if (INFRA_ON(pAd)) // must be unicast to AP
1535 else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA
1543 ========================================================================
1545 Routine Description:
1546 Check the MSDU Aggregation policy
1547 1.HT aggregation is A-MSDU
1548 2.legaacy rate aggregation is software aggregation by Ralink.
1556 ========================================================================
1558 BOOLEAN PeerIsAggreOn(
1559 IN PRTMP_ADAPTER pAd,
1561 IN PMAC_TABLE_ENTRY pMacEntry)
1563 ULONG AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
1565 if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags))
1567 if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX)
1572 #ifdef AGGREGATION_SUPPORT
1573 if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
1574 { // legacy Ralink Aggregation support
1577 #endif // AGGREGATION_SUPPORT //
1586 ========================================================================
1588 Routine Description:
1589 Check and fine the packet waiting in SW queue with highest priority
1592 pAd Pointer to our adapter
1595 pQueue Pointer to Waiting Queue
1597 IRQL = DISPATCH_LEVEL
1601 ========================================================================
1603 PQUEUE_HEADER RTMPCheckTxSwQueue(
1604 IN PRTMP_ADAPTER pAd,
1610 Number = pAd->TxSwQueue[QID_AC_BK].Number
1611 + pAd->TxSwQueue[QID_AC_BE].Number
1612 + pAd->TxSwQueue[QID_AC_VI].Number
1613 + pAd->TxSwQueue[QID_AC_VO].Number
1614 + pAd->TxSwQueue[QID_HCCA].Number;
1616 if (pAd->TxSwQueue[QID_AC_VO].Head != NULL)
1618 *pQueIdx = QID_AC_VO;
1619 return (&pAd->TxSwQueue[QID_AC_VO]);
1621 else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL)
1623 *pQueIdx = QID_AC_VI;
1624 return (&pAd->TxSwQueue[QID_AC_VI]);
1626 else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL)
1628 *pQueIdx = QID_AC_BE;
1629 return (&pAd->TxSwQueue[QID_AC_BE]);
1631 else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL)
1633 *pQueIdx = QID_AC_BK;
1634 return (&pAd->TxSwQueue[QID_AC_BK]);
1636 else if (pAd->TxSwQueue[QID_HCCA].Head != NULL)
1638 *pQueIdx = QID_HCCA;
1639 return (&pAd->TxSwQueue[QID_HCCA]);
1642 // No packet pending in Tx Sw queue
1643 *pQueIdx = QID_AC_BK;
1649 BOOLEAN RTMPFreeTXDUponTxDmaDone(
1650 IN PRTMP_ADAPTER pAd,
1653 PRTMP_TX_RING pTxRing;
1655 PNDIS_PACKET pPacket;
1657 TXD_STRUC TxD, *pOriTxD;
1659 BOOLEAN bReschedule = FALSE;
1662 ASSERT(QueIdx < NUM_OF_TX_RING);
1663 pTxRing = &pAd->TxRing[QueIdx];
1665 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF, &pTxRing->TxDmaIdx);
1666 while (pTxRing->TxSwFreeIdx != pTxRing->TxDmaIdx)
1668 // static rate also need NICUpdateFifoStaCounters() function.
1669 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
1670 NICUpdateFifoStaCounters(pAd);
1672 /* Note : If (pAd->ate.bQATxStart == TRUE), we will never reach here. */
1674 pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
1676 NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC));
1681 /*====================================================================*/
1683 pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket;
1686 #ifdef CONFIG_5VT_ENHANCE
1687 if (RTMP_GET_PACKET_5VT(pPacket))
1688 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE);
1690 #endif // CONFIG_5VT_ENHANCE //
1691 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
1692 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1694 //Always assign pNdisPacket as NULL after clear
1695 pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket = NULL;
1697 pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket;
1699 ASSERT(pPacket == NULL);
1702 #ifdef CONFIG_5VT_ENHANCE
1703 if (RTMP_GET_PACKET_5VT(pPacket))
1704 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE);
1706 #endif // CONFIG_5VT_ENHANCE //
1707 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
1708 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1710 //Always assign pNextNdisPacket as NULL after clear
1711 pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL;
1713 /*====================================================================*/
1715 pAd->RalinkCounters.TransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0);
1716 pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++;
1717 INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE);
1718 /* get tx_tdx_idx again */
1719 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &pTxRing->TxDmaIdx);
1721 NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC));
1731 ========================================================================
1733 Routine Description:
1734 Process TX Rings DMA Done interrupt, running in DPC level
1737 Adapter Pointer to our adapter
1742 IRQL = DISPATCH_LEVEL
1744 ========================================================================
1746 BOOLEAN RTMPHandleTxRingDmaDoneInterrupt(
1747 IN PRTMP_ADAPTER pAd,
1748 IN INT_SOURCE_CSR_STRUC TxRingBitmap)
1750 unsigned long IrqFlags;
1751 BOOLEAN bReschedule = FALSE;
1753 // Make sure Tx ring resource won't be used by other threads
1755 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1757 if (TxRingBitmap.field.Ac0DmaDone)
1758 bReschedule = RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BE);
1760 if (TxRingBitmap.field.HccaDmaDone)
1761 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_HCCA);
1763 if (TxRingBitmap.field.Ac3DmaDone)
1764 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VO);
1766 if (TxRingBitmap.field.Ac2DmaDone)
1767 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VI);
1769 if (TxRingBitmap.field.Ac1DmaDone)
1770 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BK);
1772 // Make sure to release Tx ring resource
1773 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1775 // Dequeue outgoing frames from TxSwQueue[] and process it
1776 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1783 ========================================================================
1785 Routine Description:
1786 Process MGMT ring DMA done interrupt, running in DPC level
1789 pAd Pointer to our adapter
1794 IRQL = DISPATCH_LEVEL
1798 ========================================================================
1800 VOID RTMPHandleMgmtRingDmaDoneInterrupt(
1801 IN PRTMP_ADAPTER pAd)
1804 PNDIS_PACKET pPacket;
1806 PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing;
1808 NdisAcquireSpinLock(&pAd->MgmtRingLock);
1810 RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pMgmtRing->TxDmaIdx);
1811 while (pMgmtRing->TxSwFreeIdx!= pMgmtRing->TxDmaIdx)
1814 pTxD = (PTXD_STRUC) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa);
1816 pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket;
1821 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
1822 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1824 pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket = NULL;
1826 pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket;
1829 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
1830 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1832 pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket = NULL;
1833 INC_RING_INDEX(pMgmtRing->TxSwFreeIdx, MGMT_RING_SIZE);
1835 NdisReleaseSpinLock(&pAd->MgmtRingLock);
1841 ========================================================================
1843 Routine Description:
1845 Adapter Pointer to our adapter. Dequeue all power safe delayed braodcast frames after beacon.
1847 IRQL = DISPATCH_LEVEL
1849 ========================================================================
1851 VOID RTMPHandleTBTTInterrupt(
1852 IN PRTMP_ADAPTER pAd)
1855 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1863 ========================================================================
1865 Routine Description:
1867 Adapter Pointer to our adapter. Rewrite beacon content before next send-out.
1869 IRQL = DISPATCH_LEVEL
1871 ========================================================================
1873 VOID RTMPHandlePreTBTTInterrupt(
1874 IN PRTMP_ADAPTER pAd)
1877 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1879 DBGPRINT(RT_DEBUG_TRACE, ("RTMPHandlePreTBTTInterrupt...\n"));
1886 VOID RTMPHandleRxCoherentInterrupt(
1887 IN PRTMP_ADAPTER pAd)
1889 WPDMA_GLO_CFG_STRUC GloCfg;
1893 DBGPRINT(RT_DEBUG_TRACE, ("====> pAd is NULL, return.\n"));
1897 DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPHandleRxCoherentInterrupt \n"));
1899 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG , &GloCfg.word);
1901 GloCfg.field.EnTXWriteBackDDONE = 0;
1902 GloCfg.field.EnableRxDMA = 0;
1903 GloCfg.field.EnableTxDMA = 0;
1904 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
1906 RTMPRingCleanUp(pAd, QID_AC_BE);
1907 RTMPRingCleanUp(pAd, QID_AC_BK);
1908 RTMPRingCleanUp(pAd, QID_AC_VI);
1909 RTMPRingCleanUp(pAd, QID_AC_VO);
1910 RTMPRingCleanUp(pAd, QID_HCCA);
1911 RTMPRingCleanUp(pAd, QID_MGMT);
1912 RTMPRingCleanUp(pAd, QID_RX);
1914 RTMPEnableRxTx(pAd);
1916 DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPHandleRxCoherentInterrupt \n"));
1920 VOID DBGPRINT_TX_RING(
1921 IN PRTMP_ADAPTER pAd,
1925 UINT32 Ac0HwIdx = 0, Ac0SwIdx = 0, AC0freeIdx;
1929 DBGPRINT_RAW(RT_DEBUG_TRACE, ("=====================================================\n " ));
1933 RTMP_IO_READ32(pAd, TX_BASE_PTR0, &Ac0Base);
1934 RTMP_IO_READ32(pAd, TX_CTX_IDX0, &Ac0SwIdx);
1935 RTMP_IO_READ32(pAd, TX_DTX_IDX0, &Ac0HwIdx);
1936 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_BE DESCRIPTOR \n " ));
1937 for (i=0;i<TX_RING_SIZE;i++)
1939 ptemp= (PULONG)pAd->TxRing[QID_AC_BE].Cell[i].AllocVa;
1940 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
1942 DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
1945 RTMP_IO_READ32(pAd, TX_BASE_PTR1, &Ac0Base);
1946 RTMP_IO_READ32(pAd, TX_CTX_IDX1, &Ac0SwIdx);
1947 RTMP_IO_READ32(pAd, TX_DTX_IDX1, &Ac0HwIdx);
1948 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_BK DESCRIPTOR \n " ));
1949 for (i=0;i<TX_RING_SIZE;i++)
1951 ptemp= (PULONG)pAd->TxRing[QID_AC_BK].Cell[i].AllocVa;
1952 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
1954 DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
1957 RTMP_IO_READ32(pAd, TX_BASE_PTR2, &Ac0Base);
1958 RTMP_IO_READ32(pAd, TX_CTX_IDX2, &Ac0SwIdx);
1959 RTMP_IO_READ32(pAd, TX_DTX_IDX2, &Ac0HwIdx);
1960 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_VI DESCRIPTOR \n " ));
1961 for (i=0;i<TX_RING_SIZE;i++)
1963 ptemp= (PULONG)pAd->TxRing[QID_AC_VI].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_PTR3, &Ac0Base);
1970 RTMP_IO_READ32(pAd, TX_CTX_IDX3, &Ac0SwIdx);
1971 RTMP_IO_READ32(pAd, TX_DTX_IDX3, &Ac0HwIdx);
1972 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_VO DESCRIPTOR \n " ));
1973 for (i=0;i<TX_RING_SIZE;i++)
1975 ptemp= (PULONG)pAd->TxRing[QID_AC_VO].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_PTR5, &Ac0Base);
1982 RTMP_IO_READ32(pAd, TX_CTX_IDX5, &Ac0SwIdx);
1983 RTMP_IO_READ32(pAd, TX_DTX_IDX5, &Ac0HwIdx);
1984 DBGPRINT_RAW(RT_DEBUG_TRACE, (" All QID_MGMT DESCRIPTOR \n " ));
1985 for (i=0;i<MGMT_RING_SIZE;i++)
1987 ptemp= (PULONG)pAd->MgmtRing.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 " ));
1994 DBGPRINT_ERR(("DBGPRINT_TX_RING(Ring %d) not supported\n", QueIdx));
1997 AC0freeIdx = pAd->TxRing[QueIdx].TxSwFreeIdx;
1999 DBGPRINT(RT_DEBUG_TRACE,("TxRing%d, TX_DTX_IDX=%d, TX_CTX_IDX=%d\n", QueIdx, Ac0HwIdx, Ac0SwIdx));
2000 DBGPRINT_RAW(RT_DEBUG_TRACE,(" TxSwFreeIdx[%d]", AC0freeIdx));
2001 DBGPRINT_RAW(RT_DEBUG_TRACE,(" pending-NDIS=%ld\n", pAd->RalinkCounters.PendingNdisPacketCount));
2007 VOID DBGPRINT_RX_RING(
2008 IN PRTMP_ADAPTER pAd)
2011 UINT32 Ac0HwIdx = 0, Ac0SwIdx = 0, AC0freeIdx;
2015 DBGPRINT_RAW(RT_DEBUG_TRACE, ("=====================================================\n " ));
2016 RTMP_IO_READ32(pAd, RX_BASE_PTR, &Ac0Base);
2017 RTMP_IO_READ32(pAd, RX_CRX_IDX, &Ac0SwIdx);
2018 RTMP_IO_READ32(pAd, RX_DRX_IDX, &Ac0HwIdx);
2019 AC0freeIdx = pAd->RxRing.RxSwReadIdx;
2021 DBGPRINT_RAW(RT_DEBUG_TRACE, ("All RX DSP \n " ));
2022 for (i=0;i<RX_RING_SIZE;i++)
2024 ptemp = (UINT32 *)pAd->RxRing.Cell[i].AllocVa;
2025 DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08x: %08x: %08x: %08x\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
2027 DBGPRINT(RT_DEBUG_TRACE,("RxRing, RX_DRX_IDX=%d, RX_CRX_IDX=%d \n", Ac0HwIdx, Ac0SwIdx));
2028 DBGPRINT_RAW(RT_DEBUG_TRACE,(" RxSwReadIdx [%d]=", AC0freeIdx));
2029 DBGPRINT_RAW(RT_DEBUG_TRACE,(" pending-NDIS=%ld\n", pAd->RalinkCounters.PendingNdisPacketCount));
2033 ========================================================================
2035 Routine Description:
2036 Suspend MSDU transmission
2039 pAd Pointer to our adapter
2046 ========================================================================
2048 VOID RTMPSuspendMsduTransmission(
2049 IN PRTMP_ADAPTER pAd)
2051 DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n"));
2055 // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
2056 // use Lowbound as R66 value on ScanNextChannel(...)
2058 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue);
2060 // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)
2061 RTMPSetAGCInitValue(pAd, BW_20);
2063 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
2068 ========================================================================
2070 Routine Description:
2071 Resume MSDU transmission
2074 pAd Pointer to our adapter
2079 IRQL = DISPATCH_LEVEL
2083 ========================================================================
2085 VOID RTMPResumeMsduTransmission(
2086 IN PRTMP_ADAPTER pAd)
2088 DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
2091 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue);
2093 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
2094 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
2098 UINT deaggregate_AMSDU_announce(
2099 IN PRTMP_ADAPTER pAd,
2100 PNDIS_PACKET pPacket,
2105 USHORT SubFrameSize;
2106 PHEADER_802_3 pAMSDUsubheader;
2108 UCHAR Header802_3[14];
2110 PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP;
2111 PNDIS_PACKET pClonePacket;
2117 while (DataSize > LENGTH_802_3)
2122 pAMSDUsubheader = (PHEADER_802_3)pData;
2123 PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8);
2124 SubFrameSize = PayloadSize + LENGTH_802_3;
2127 if ((DataSize < SubFrameSize) || (PayloadSize > 1518 ))
2132 pPayload = pData + LENGTH_802_3;
2134 pSA = pData + MAC_ADDR_LEN;
2136 // convert to 802.3 header
2137 CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP);
2139 if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) )
2141 // avoid local heap overflow, use dyanamic allocation
2142 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
2143 memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize);
2144 Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize;
2145 WpaEAPOLKeyAction(pAd, Elem);
2149 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2151 if (pRemovedLLCSNAP)
2153 pPayload -= LENGTH_802_3;
2154 PayloadSize += LENGTH_802_3;
2155 NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3);
2159 pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
2162 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2163 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket));
2167 // A-MSDU has padding to multiple of 4 including subframe header.
2168 // align SubFrameSize up to multiple of 4
2169 SubFrameSize = (SubFrameSize+3)&(~0x3);
2172 if (SubFrameSize > 1528 || SubFrameSize < 32)
2177 if (DataSize > SubFrameSize)
2179 pData += SubFrameSize;
2180 DataSize -= SubFrameSize;
2189 // finally release original rx packet
2190 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
2196 UINT BA_Reorder_AMSDU_Annnounce(
2197 IN PRTMP_ADAPTER pAd,
2198 IN PNDIS_PACKET pPacket)
2204 pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
2205 DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
2207 nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
2214 ==========================================================================
2216 Look up the MAC address in the MAC table. Return NULL if not found.
2218 pEntry - pointer to the MAC entry; NULL is not found
2219 ==========================================================================
2221 MAC_TABLE_ENTRY *MacTableLookup(
2222 IN PRTMP_ADAPTER pAd,
2226 MAC_TABLE_ENTRY *pEntry = NULL;
2228 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
2229 pEntry = pAd->MacTab.Hash[HashIdx];
2231 while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh))
2233 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
2238 pEntry = pEntry->pNext;
2244 MAC_TABLE_ENTRY *MacTableInsertEntry(
2245 IN PRTMP_ADAPTER pAd,
2248 IN BOOLEAN CleanAll)
2252 MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
2255 if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
2260 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2262 if (pAd->StaCfg.BssType == BSS_INFRA)
2265 // allocate one MAC entry
2266 NdisAcquireSpinLock(&pAd->MacTabLock);
2267 for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++) // skip entry#0 so that "entry index == AID" for fast lookup
2269 // pick up the first available vacancy
2270 if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
2271 (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
2272 (pAd->MacTab.Content[i].ValidAsApCli== FALSE) &&
2273 (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
2276 pEntry = &pAd->MacTab.Content[i];
2277 if (CleanAll == TRUE)
2279 pEntry->MaxSupportedRate = RATE_11;
2280 pEntry->CurrTxRate = RATE_11;
2281 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
2282 pEntry->PairwiseKey.KeyLen = 0;
2283 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
2286 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2288 pEntry->ValidAsCLI = TRUE;
2289 pEntry->ValidAsWDS = FALSE;
2290 pEntry->ValidAsApCli = FALSE;
2291 pEntry->ValidAsMesh = FALSE;
2292 pEntry->ValidAsDls = FALSE;
2296 pEntry->bIAmBadAtheros = FALSE;
2298 pEntry->CMTimerRunning = FALSE;
2299 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
2300 pEntry->RSNIE_Len = 0;
2301 NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
2302 pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
2304 if (pEntry->ValidAsMesh)
2305 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH);
2306 else if (pEntry->ValidAsApCli)
2307 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI);
2308 else if (pEntry->ValidAsWDS)
2309 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS);
2311 pEntry->apidx = apidx;
2314 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2316 pEntry->AuthMode = pAd->StaCfg.AuthMode;
2317 pEntry->WepStatus = pAd->StaCfg.WepStatus;
2318 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
2319 AsicRemovePairwiseKeyEntry(pAd, pEntry->apidx, (UCHAR)i);
2323 pEntry->GTKState = REKEY_NEGOTIATING;
2324 pEntry->PairwiseKey.KeyLen = 0;
2325 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
2327 if ((pAd->OpMode == OPMODE_STA) &&
2328 (pAd->StaCfg.BssType == BSS_ADHOC))
2329 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
2331 pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
2333 pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
2334 COPY_MAC_ADDR(pEntry->Addr, pAddr);
2335 pEntry->Sst = SST_NOT_AUTH;
2336 pEntry->AuthState = AS_NOT_AUTH;
2337 pEntry->Aid = (USHORT)i; //0;
2338 pEntry->CapabilityInfo = 0;
2339 pEntry->PsMode = PWR_ACTIVE;
2340 pEntry->PsQIdleCount = 0;
2341 pEntry->NoDataIdleCount = 0;
2342 pEntry->ContinueTxFailCnt = 0;
2343 InitializeQueueHeader(&pEntry->PsQueue);
2346 pAd->MacTab.Size ++;
2347 // Add this entry into ASIC RX WCID search table
2348 RT28XX_STA_ENTRY_ADD(pAd, pEntry);
2352 DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size));
2357 // add this MAC entry into HASH table
2360 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
2361 if (pAd->MacTab.Hash[HashIdx] == NULL)
2363 pAd->MacTab.Hash[HashIdx] = pEntry;
2367 pCurrEntry = pAd->MacTab.Hash[HashIdx];
2368 while (pCurrEntry->pNext != NULL)
2369 pCurrEntry = pCurrEntry->pNext;
2370 pCurrEntry->pNext = pEntry;
2374 NdisReleaseSpinLock(&pAd->MacTabLock);
2379 ==========================================================================
2381 Delete a specified client from MAC table
2382 ==========================================================================
2384 BOOLEAN MacTableDeleteEntry(
2385 IN PRTMP_ADAPTER pAd,
2390 MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
2393 if (wcid >= MAX_LEN_OF_MAC_TABLE)
2396 NdisAcquireSpinLock(&pAd->MacTabLock);
2398 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
2399 pEntry = &pAd->MacTab.Content[wcid];
2401 if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh
2404 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
2407 // Delete this entry from ASIC on-chip WCID Table
2408 RT28XX_STA_ENTRY_MAC_RESET(pAd, wcid);
2410 // free resources of BA
2411 BASessionTearDownALL(pAd, pEntry->Aid);
2414 pProbeEntry = pAd->MacTab.Hash[HashIdx];
2415 ASSERT(pProbeEntry);
2420 if (pProbeEntry == pEntry)
2422 if (pPrevEntry == NULL)
2424 pAd->MacTab.Hash[HashIdx] = pEntry->pNext;
2428 pPrevEntry->pNext = pEntry->pNext;
2433 pPrevEntry = pProbeEntry;
2434 pProbeEntry = pProbeEntry->pNext;
2435 } while (pProbeEntry);
2438 ASSERT(pProbeEntry != NULL);
2440 RT28XX_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
2443 if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
2445 RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
2446 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
2450 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
2451 pAd->MacTab.Size --;
2452 DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size));
2456 printk("\n%s: Impossible Wcid = %d !!!!!\n", __func__, wcid);
2460 NdisReleaseSpinLock(&pAd->MacTabLock);
2462 //Reset operating mode when no Sta.
2463 if (pAd->MacTab.Size == 0)
2465 pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
2466 AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/);
2474 ==========================================================================
2476 This routine reset the entire MAC table. All packets pending in
2477 the power-saving queues are freed here.
2478 ==========================================================================
2481 IN PRTMP_ADAPTER pAd)
2485 DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
2486 //NdisAcquireSpinLock(&pAd->MacTabLock);
2488 for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
2490 RT28XX_STA_ENTRY_MAC_RESET(pAd, i);
2491 if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
2493 // free resources of BA
2494 BASessionTearDownALL(pAd, i);
2496 pAd->MacTab.Content[i].ValidAsCLI = FALSE;
2501 //AsicDelWcidTab(pAd, i);
2509 ==========================================================================
2512 IRQL = DISPATCH_LEVEL
2514 ==========================================================================
2517 IN PRTMP_ADAPTER pAd,
2518 IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
2520 IN USHORT CapabilityInfo,
2522 IN USHORT ListenIntv)
2524 COPY_MAC_ADDR(AssocReq->Addr, pAddr);
2525 // Add mask to support 802.11b mode only
2526 AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request
2527 AssocReq->Timeout = Timeout;
2528 AssocReq->ListenIntv = ListenIntv;
2533 ==========================================================================
2536 IRQL = DISPATCH_LEVEL
2538 ==========================================================================
2540 VOID DisassocParmFill(
2541 IN PRTMP_ADAPTER pAd,
2542 IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
2546 COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
2547 DisassocReq->Reason = Reason;
2552 ========================================================================
2554 Routine Description:
2555 Check the out going frame, if this is an DHCP or ARP datagram
2556 will be duplicate another frame at low data rate transmit.
2559 pAd Pointer to our adapter
2560 pPacket Pointer to outgoing Ndis frame
2563 TRUE To be duplicate at Low data rate transmit. (1mb)
2566 IRQL = DISPATCH_LEVEL
2570 MAC header + IP Header + UDP Header
2574 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
2576 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
2579 port 0x43 means Bootstrap Protocol, server.
2580 Port 0x44 means Bootstrap Protocol, client.
2582 ========================================================================
2585 BOOLEAN RTMPCheckDHCPFrame(
2586 IN PRTMP_ADAPTER pAd,
2587 IN PNDIS_PACKET pPacket)
2589 PACKET_INFO PacketInfo;
2590 ULONG NumberOfBytesRead = 0;
2591 ULONG CurrentOffset = 0;
2592 PVOID pVirtualAddress = NULL;
2593 UINT NdisBufferLength;
2596 UCHAR ByteOffset36 = 0;
2597 UCHAR ByteOffset38 = 0;
2598 BOOLEAN ReadFirstParm = TRUE;
2600 RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength);
2602 NumberOfBytesRead += NdisBufferLength;
2603 pSrc = (PUCHAR) pVirtualAddress;
2604 Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
2607 // Check DHCP & BOOTP protocol
2609 while (NumberOfBytesRead <= PacketInfo.TotalPacketLength)
2611 if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE))
2613 CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength);
2614 ByteOffset36 = *(pSrc + CurrentOffset);
2615 ReadFirstParm = FALSE;
2618 if (NumberOfBytesRead >= 37)
2620 CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength);
2621 ByteOffset38 = *(pSrc + CurrentOffset);
2628 // Check for DHCP & BOOTP protocol
2629 if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43))
2632 // 2054 (hex 0806) for ARP datagrams
2633 // if this packet is not ARP datagrams, then do nothing
2634 // ARP datagrams will also be duplicate at 1mb broadcast frames
2636 if (Protocol != 0x0806 )
2644 BOOLEAN RTMPCheckEtherType(
2645 IN PRTMP_ADAPTER pAd,
2646 IN PNDIS_PACKET pPacket)
2652 UINT16 srcPort, dstPort;
2653 BOOLEAN status = TRUE;
2656 pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
2657 pktLen = GET_OS_PKT_LEN(pPacket);
2661 RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
2663 // get Ethernet protocol field
2664 TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13];
2666 pSrcBuf += LENGTH_802_3; // Skip the Ethernet Header.
2668 if (TypeLen <= 1500)
2669 { // 802.3, 802.3 LLC
2671 DestMAC(6) + SrcMAC(6) + Lenght(2) +
2672 DSAP(1) + SSAP(1) + Control(1) +
2673 if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
2674 => + SNAP (5, OriginationID(3) + etherType(2))
2676 if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03)
2678 Sniff2BytesFromNdisBuffer(pSrcBuf, 6, &Byte0, &Byte1);
2679 RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
2680 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2681 pSrcBuf += 8; // Skip this LLC/SNAP header
2685 //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.
2689 // If it's a VLAN packet, get the real Type/Length field.
2690 if (TypeLen == 0x8100)
2692 /* 0x8100 means VLAN packets */
2694 /* Dest. MAC Address (6-bytes) +
2695 Source MAC Address (6-bytes) +
2696 Length/Type = 802.1Q Tag Type (2-byte) +
2697 Tag Control Information (2-bytes) +
2698 Length / Type (2-bytes) +
2699 data payload (0-n bytes) +
2701 Frame Check Sequence (4-bytes) */
2703 RTMP_SET_PACKET_VLAN(pPacket, 1);
2704 Sniff2BytesFromNdisBuffer(pSrcBuf, 2, &Byte0, &Byte1);
2705 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2707 pSrcBuf += 4; // Skip the VLAN Header.
2714 ASSERT((pktLen > 34));
2715 if (*(pSrcBuf + 9) == 0x11)
2717 ASSERT((pktLen > 34)); // 14 for ethernet header, 20 for IP header
2719 pSrcBuf += 20; // Skip the IP header
2720 srcPort = OS_NTOHS(*((UINT16 *)pSrcBuf));
2721 dstPort = OS_NTOHS(*((UINT16 *)(pSrcBuf +2)));
2723 if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44))
2724 { //It's a BOOTP/DHCP packet
2725 RTMP_SET_PACKET_DHCP(pPacket, 1);
2733 RTMP_SET_PACKET_DHCP(pPacket, 1);
2739 RTMP_SET_PACKET_EAPOL(pPacket, 1);
2753 VOID Update_Rssi_Sample(
2754 IN PRTMP_ADAPTER pAd,
2755 IN RSSI_SAMPLE *pRssi,
2756 IN PRXWI_STRUC pRxWI)
2758 CHAR rssi0 = pRxWI->RSSI0;
2759 CHAR rssi1 = pRxWI->RSSI1;
2760 CHAR rssi2 = pRxWI->RSSI2;
2764 pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0);
2765 pRssi->AvgRssi0X8 = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
2766 pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
2771 pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1);
2772 pRssi->AvgRssi1X8 = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
2773 pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
2778 pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2);
2779 pRssi->AvgRssi2X8 = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
2780 pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
2786 // Normal legacy Rx packet indication
2787 VOID Indicate_Legacy_Packet(
2788 IN PRTMP_ADAPTER pAd,
2790 IN UCHAR FromWhichBSSID)
2792 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2793 UCHAR Header802_3[LENGTH_802_3];
2795 // 1. get 802.3 Header
2797 // a. pointer pRxBlk->pData to payload
2798 // b. modify pRxBlk->DataSize
2799 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2800 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2802 if (pRxBlk->DataSize > MAX_RX_PKT_LEN)
2806 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2811 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
2814 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2817 // pass this 802.3 packet to upper layer or forward this packet to WM directly
2819 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2820 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
2824 // Normal, AMPDU or AMSDU
2825 VOID CmmRxnonRalinkFrameIndicate(
2826 IN PRTMP_ADAPTER pAd,
2828 IN UCHAR FromWhichBSSID)
2830 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
2832 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2836 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
2839 Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2843 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
2849 VOID CmmRxRalinkFrameIndicate(
2850 IN PRTMP_ADAPTER pAd,
2851 IN MAC_TABLE_ENTRY *pEntry,
2853 IN UCHAR FromWhichBSSID)
2855 UCHAR Header802_3[LENGTH_802_3];
2857 UINT16 Payload1Size, Payload2Size;
2859 PNDIS_PACKET pPacket2 = NULL;
2863 Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8);
2865 if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize))
2867 /* skip two byte MSDU2 len */
2869 pRxBlk->DataSize -= 2;
2874 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2878 // get 802.3 Header and remove LLC
2879 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2880 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2882 ASSERT(pRxBlk->pRxPacket);
2884 // Ralink Aggregation frame
2885 pAd->RalinkCounters.OneSecRxAggregationCount ++;
2886 Payload1Size = pRxBlk->DataSize - Msdu2Size;
2887 Payload2Size = Msdu2Size - LENGTH_802_3;
2889 pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
2891 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2892 pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID);
2897 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2901 // update payload size of 1st packet
2902 pRxBlk->DataSize = Payload1Size;
2903 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2905 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2906 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID);
2910 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2911 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
2916 #define RESET_FRAGFRAME(_fragFrame) \
2918 _fragFrame.RxSize = 0; \
2919 _fragFrame.Sequence = 0; \
2920 _fragFrame.LastFrag = 0; \
2921 _fragFrame.Flags = 0; \
2925 PNDIS_PACKET RTMPDeFragmentDataFrame(
2926 IN PRTMP_ADAPTER pAd,
2929 PHEADER_802_11 pHeader = pRxBlk->pHeader;
2930 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2931 UCHAR *pData = pRxBlk->pData;
2932 USHORT DataSize = pRxBlk->DataSize;
2933 PNDIS_PACKET pRetPacket = NULL;
2934 UCHAR *pFragBuffer = NULL;
2935 BOOLEAN bReassDone = FALSE;
2936 UCHAR HeaderRoom = 0;
2941 HeaderRoom = pData - (UCHAR *)pHeader;
2943 // Re-assemble the fragmented packets
2944 if (pHeader->Frag == 0) // Frag. Number is 0 : First frag or only one pkt
2946 // the first pkt of fragment, record it.
2947 if (pHeader->FC.MoreFrag)
2949 ASSERT(pAd->FragFrame.pFragPacket);
2950 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2951 pAd->FragFrame.RxSize = DataSize + HeaderRoom;
2952 NdisMoveMemory(pFragBuffer, pHeader, pAd->FragFrame.RxSize);
2953 pAd->FragFrame.Sequence = pHeader->Sequence;
2954 pAd->FragFrame.LastFrag = pHeader->Frag; // Should be 0
2955 ASSERT(pAd->FragFrame.LastFrag == 0);
2956 goto done; // end of processing this frame
2959 else //Middle & End of fragment
2961 if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
2962 (pHeader->Frag != (pAd->FragFrame.LastFrag + 1)))
2964 // Fragment is not the same sequence or out of fragment number order
2965 // Reset Fragment control blk
2966 RESET_FRAGFRAME(pAd->FragFrame);
2967 DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n"));
2968 goto done; // give up this frame
2970 else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE)
2972 // Fragment frame is too large, it exeeds the maximum frame size.
2973 // Reset Fragment control blk
2974 RESET_FRAGFRAME(pAd->FragFrame);
2975 DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
2976 goto done; // give up this frame
2980 // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.
2981 // In this case, we will dropt it.
2983 if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H)))
2985 DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag));
2986 goto done; // give up this frame
2989 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2991 // concatenate this fragment into the re-assembly buffer
2992 NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize);
2993 pAd->FragFrame.RxSize += DataSize;
2994 pAd->FragFrame.LastFrag = pHeader->Frag; // Update fragment number
2997 if (pHeader->FC.MoreFrag == FALSE)
3004 // always release rx fragmented packet
3005 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
3007 // return defragmented packet if packet is reassembled completely
3008 // otherwise return NULL
3011 PNDIS_PACKET pNewFragPacket;
3013 // allocate a new packet buffer for fragment
3014 pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
3018 pRetPacket = pAd->FragFrame.pFragPacket;
3019 pAd->FragFrame.pFragPacket = pNewFragPacket;
3020 pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
3021 pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom;
3022 pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
3023 pRxBlk->pRxPacket = pRetPacket;
3027 RESET_FRAGFRAME(pAd->FragFrame);
3035 VOID Indicate_AMSDU_Packet(
3036 IN PRTMP_ADAPTER pAd,
3038 IN UCHAR FromWhichBSSID)
3042 update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
3043 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
3044 nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize);
3047 VOID Indicate_EAPOL_Packet(
3048 IN PRTMP_ADAPTER pAd,
3050 IN UCHAR FromWhichBSSID)
3052 MAC_TABLE_ENTRY *pEntry = NULL;
3054 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3056 pEntry = &pAd->MacTab.Content[BSSID_WCID];
3057 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
3063 DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
3065 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
3070 #define BCN_TBTT_OFFSET 64 //defer 64 us
3071 VOID ReSyncBeaconTime(
3072 IN PRTMP_ADAPTER pAd)
3078 Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
3080 pAd->TbttTickCount++;
3083 // The updated BeaconInterval Value will affect Beacon Interval after two TBTT
3084 // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
3086 if (Offset == (BCN_TBTT_OFFSET-2))
3088 BCN_TIME_CFG_STRUC csr;
3089 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
3090 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; // ASIC register in units of 1/16 TU = 64us
3091 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
3095 if (Offset == (BCN_TBTT_OFFSET-1))
3097 BCN_TIME_CFG_STRUC csr;
3099 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
3100 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU
3101 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);