2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 *************************************************************************
28 #include "../rt_config.h"
30 #define MAX_TX_IN_TBTT (16)
33 UCHAR SNAP_802_1H[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
34 UCHAR SNAP_BRIDGE_TUNNEL[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8};
35 // Add Cisco Aironet SNAP heade for CCX2 support
36 UCHAR SNAP_AIRONET[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00};
37 UCHAR CKIP_LLC_SNAP[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02};
38 UCHAR EAPOL_LLC_SNAP[]= {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e};
39 UCHAR EAPOL[] = {0x88, 0x8e};
40 UCHAR TPID[] = {0x81, 0x00}; /* VLAN related */
42 UCHAR IPX[] = {0x81, 0x37};
43 UCHAR APPLE_TALK[] = {0x80, 0xf3};
44 UCHAR RateIdToPlcpSignal[12] = {
45 0, /* RATE_1 */ 1, /* RATE_2 */ 2, /* RATE_5_5 */ 3, /* RATE_11 */ // see BBP spec
46 11, /* RATE_6 */ 15, /* RATE_9 */ 10, /* RATE_12 */ 14, /* RATE_18 */ // see IEEE802.11a-1999 p.14
47 9, /* RATE_24 */ 13, /* RATE_36 */ 8, /* RATE_48 */ 12 /* RATE_54 */ }; // see IEEE802.11a-1999 p.14
49 UCHAR OfdmSignalToRateId[16] = {
50 RATE_54, RATE_54, RATE_54, RATE_54, // OFDM PLCP Signal = 0, 1, 2, 3 respectively
51 RATE_54, RATE_54, RATE_54, RATE_54, // OFDM PLCP Signal = 4, 5, 6, 7 respectively
52 RATE_48, RATE_24, RATE_12, RATE_6, // OFDM PLCP Signal = 8, 9, 10, 11 respectively
53 RATE_54, RATE_36, RATE_18, RATE_9, // OFDM PLCP Signal = 12, 13, 14, 15 respectively
56 UCHAR OfdmRateToRxwiMCS[12] = {
58 0, 1, 2, 3, // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3
59 4, 5, 6, 7, // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7
61 UCHAR RxwiMCSToOfdmRate[12] = {
62 RATE_6, RATE_9, RATE_12, RATE_18,
63 RATE_24, RATE_36, RATE_48, RATE_54, // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3
64 4, 5, 6, 7, // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7
67 char* MCSToMbps[] = {"1Mbps","2Mbps","5.5Mbps","11Mbps","06Mbps","09Mbps","12Mbps","18Mbps","24Mbps","36Mbps","48Mbps","54Mbps","MM-0","MM-1","MM-2","MM-3","MM-4","MM-5","MM-6","MM-7","MM-8","MM-9","MM-10","MM-11","MM-12","MM-13","MM-14","MM-15","MM-32","ee1","ee2","ee3"};
69 UCHAR default_cwmin[]={CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1, CW_MIN_IN_BITS-2};
70 UCHAR default_sta_aifsn[]={3,7,2,2};
72 UCHAR MapUserPriorityToAccessCategory[8] = {QID_AC_BE, QID_AC_BK, QID_AC_BK, QID_AC_BE, QID_AC_VI, QID_AC_VI, QID_AC_VO, QID_AC_VO};
76 ========================================================================
79 API for MLME to transmit management frame to AP (BSS Mode)
80 or station (IBSS Mode)
83 pAd Pointer to our adapter
84 pData Pointer to the outgoing 802.11 frame
85 Length Size of outgoing management frame
97 ========================================================================
99 NDIS_STATUS MiniportMMRequest(
100 IN PRTMP_ADAPTER pAd,
105 PNDIS_PACKET pPacket;
106 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
109 unsigned long IrqFlags = 0;
112 UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN];
114 ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
120 IrqState = pAd->irq_disabled;
123 if ((pAd->MACVersion == 0x28600100) && (!IrqState))
124 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
128 // Reset is in progress, stop immediately
129 if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
130 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)||
131 !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
133 Status = NDIS_STATUS_FAILURE;
137 // Check Free priority queue
138 // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing.
141 if (pAd->MACVersion == 0x28600100)
143 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
147 FreeNum = GET_MGMTRING_FREENO(pAd);
152 // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870
153 NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE));
154 Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE), pData, Length);
155 if (Status != NDIS_STATUS_SUCCESS)
157 DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
161 //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
162 //pAd->CommonCfg.MlmeRate = RATE_2;
165 Status = MlmeHardTransmit(pAd, QueIdx, pPacket);
166 if (Status != NDIS_STATUS_SUCCESS)
167 RTMPFreeNdisPacket(pAd, pPacket);
171 pAd->RalinkCounters.MgmtRingFullCount++;
172 DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n",
173 QueIdx, pAd->RalinkCounters.MgmtRingFullCount));
180 if ((pAd->MACVersion == 0x28600100) && (!IrqState))
181 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
187 NDIS_STATUS MiniportMMRequestUnlock(
188 IN PRTMP_ADAPTER pAd,
193 PNDIS_PACKET pPacket;
194 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
201 ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
205 // Reset is in progress, stop immediately
206 if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
207 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)||
208 !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
210 Status = NDIS_STATUS_FAILURE;
214 // Check Free priority queue
215 // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing.
217 if (pAd->MACVersion == 0x28600100)
219 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
220 SW_TX_IDX = pAd->TxRing[QueIdx].TxCpuIdx;
221 pTxD = (PTXD_STRUC) pAd->TxRing[QueIdx].Cell[SW_TX_IDX].AllocVa;
225 FreeNum = GET_MGMTRING_FREENO(pAd);
226 SW_TX_IDX = pAd->MgmtRing.TxCpuIdx;
227 pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[SW_TX_IDX].AllocVa;
231 NdisZeroMemory(&TXWI, TXWI_SIZE);
232 Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&TXWI, TXWI_SIZE, pData, Length);
233 if (Status != NDIS_STATUS_SUCCESS)
235 DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
239 Status = MlmeHardTransmit(pAd, QueIdx, pPacket);
240 if (Status != NDIS_STATUS_SUCCESS)
241 RTMPFreeNdisPacket(pAd, pPacket);
245 pAd->RalinkCounters.MgmtRingFullCount++;
246 DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing\n", QueIdx));
257 ========================================================================
260 Copy frame from waiting queue into relative ring buffer and set
261 appropriate ASIC register to kick hardware transmit function
264 pAd Pointer to our adapter
265 pBuffer Pointer to memory of outgoing frame
266 Length Size of outgoing management frame
274 IRQL = DISPATCH_LEVEL
278 ========================================================================
280 NDIS_STATUS MlmeHardTransmit(
281 IN PRTMP_ADAPTER pAd,
283 IN PNDIS_PACKET pPacket)
285 if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
287 return NDIS_STATUS_FAILURE;
291 if ( pAd->MACVersion == 0x28600100 )
292 return MlmeHardTransmitTxRing(pAd,QueIdx,pPacket);
295 return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
300 NDIS_STATUS MlmeHardTransmitTxRing(
301 IN PRTMP_ADAPTER pAd,
303 IN PNDIS_PACKET pPacket)
305 PACKET_INFO PacketInfo;
309 PHEADER_802_11 pHeader_802_11;
310 BOOLEAN bAckRequired, bInsertTimestamp;
313 ULONG SwIdx = pAd->TxRing[QueIdx].TxCpuIdx;
314 PTXWI_STRUC pFirstTxWI;
316 MAC_TABLE_ENTRY *pMacEntry = NULL;
319 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
321 if (pSrcBufVA == NULL)
323 // The buffer shouldn't be NULL
324 return NDIS_STATUS_FAILURE;
327 // Make sure MGMT ring resource won't be used by other threads
328 //NdisAcquireSpinLock(&pAd->TxRingLock);
330 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
334 //NdisReleaseSpinLock(&pAd->TxRingLock);
335 return NDIS_STATUS_FAILURE;
338 SwIdx = pAd->TxRing[QueIdx].TxCpuIdx;
340 pTxD = (PTXD_STRUC) pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa;
342 if (pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket)
344 printk("MlmeHardTransmit Error\n");
345 return NDIS_STATUS_FAILURE;
348 // outgoing frame always wakeup PHY to prevent frame lost
349 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
350 AsicForceWakeup(pAd, FROM_TX);
352 pFirstTxWI =(PTXWI_STRUC)pSrcBufVA;
354 pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXWI_SIZE);
355 if (pHeader_802_11->Addr1[0] & 0x01)
357 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
361 MlmeRate = pAd->CommonCfg.MlmeRate;
364 if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
365 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
367 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
370 // Verify Mlme rate for a / g bands.
371 if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
375 // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
376 // Snice it's been set to 0 while on MgtMacHeaderInit
377 // By the way this will cause frame to be send on PWR_SAVE failed.
380 // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
382 // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
383 if (pHeader_802_11->FC.Type != BTYPE_DATA)
385 if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_REQ) || !(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
387 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
391 pHeader_802_11->FC.PwrMgmt = pAd->CommonCfg.bAPSDForcePowerSave;
395 bInsertTimestamp = FALSE;
396 if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
398 bAckRequired = FALSE;
400 else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
402 if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
404 bAckRequired = FALSE;
405 pHeader_802_11->Duration = 0;
410 pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
411 if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
413 bInsertTimestamp = TRUE;
417 pHeader_802_11->Sequence = pAd->Sequence++;
418 if (pAd->Sequence > 0xfff)
420 // Before radar detection done, mgmt frame can not be sent but probe req
421 // Because we need to use probe req to trigger driver to send probe req in passive scan
422 if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
423 && (pAd->CommonCfg.bIEEE80211H == 1)
424 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
426 DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
427 return (NDIS_STATUS_FAILURE);
431 // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
432 // should always has only one ohysical buffer, and the whole frame size equals
433 // to the first scatter buffer size
436 // Initialize TX Descriptor
437 // For inter-frame gap, the number is for this frame and next frame
438 // For MLME rate, we will fix as 2Mb to match other vendor's implement
440 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
441 // Only beacon use Nseq=TRUE. So here we use Nseq=FALSE.
442 if (pMacEntry == NULL)
444 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
445 0, RESERVED_WCID, (SrcBufLen - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
449 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
450 bInsertTimestamp, FALSE, bAckRequired, FALSE,
451 0, pMacEntry->Aid, (SrcBufLen - TXWI_SIZE),
452 pMacEntry->MaxHTPhyMode.field.MCS, 0,
453 (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
454 IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
457 pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket = pPacket;
458 pAd->TxRing[QueIdx].Cell[SwIdx].pNextNdisPacket = NULL;
460 SrcBufPA = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE);
463 RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_EDCA);
466 pTxD->SDLen0 = SrcBufLen;
468 pTxD->SDPtr0 = SrcBufPA;
471 pAd->RalinkCounters.KickTxCount++;
472 pAd->RalinkCounters.OneSecTxDoneCount++;
474 // Increase TX_CTX_IDX, but write to register later.
475 INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE);
477 RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx*0x10, pAd->TxRing[QueIdx].TxCpuIdx);
479 return NDIS_STATUS_SUCCESS;
483 NDIS_STATUS MlmeHardTransmitMgmtRing(
484 IN PRTMP_ADAPTER pAd,
486 IN PNDIS_PACKET pPacket)
488 PACKET_INFO PacketInfo;
491 PHEADER_802_11 pHeader_802_11;
492 BOOLEAN bAckRequired, bInsertTimestamp;
494 PTXWI_STRUC pFirstTxWI;
495 MAC_TABLE_ENTRY *pMacEntry = NULL;
497 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
498 RTMP_SEM_LOCK(&pAd->MgmtRingLock);
501 if (pSrcBufVA == NULL)
503 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
504 return NDIS_STATUS_FAILURE;
507 // outgoing frame always wakeup PHY to prevent frame lost
508 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
510 AsicForceWakeup(pAd, FROM_TX);
513 AsicForceWakeup(pAd, TRUE);
516 pFirstTxWI = (PTXWI_STRUC)(pSrcBufVA + TXINFO_SIZE);
517 pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); //TXWI_SIZE);
519 if (pHeader_802_11->Addr1[0] & 0x01)
521 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
525 MlmeRate = pAd->CommonCfg.MlmeRate;
528 // Verify Mlme rate for a / g bands.
529 if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
532 if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
533 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
535 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
539 // Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode.
540 if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED
541 || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED
544 if (pAd->LatchRfRegs.Channel > 14)
545 pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
547 pAd->CommonCfg.MlmeTransmit.field.MODE = 0;
552 // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
553 // Snice it's been set to 0 while on MgtMacHeaderInit
554 // By the way this will cause frame to be send on PWR_SAVE failed.
556 // pHeader_802_11->FC.PwrMgmt = 0; // (pAd->StaCfg.Psm == PWR_SAVE);
558 // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
560 // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
561 if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL))
563 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
564 (pHeader_802_11->FC.SubType == SUBTYPE_ACTION))
565 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
567 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
570 bInsertTimestamp = FALSE;
571 if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
573 //Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue.
574 if ((pAd->OpMode == OPMODE_STA) && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL))
576 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
578 bAckRequired = FALSE;
580 else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
582 if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
584 bAckRequired = FALSE;
585 pHeader_802_11->Duration = 0;
590 pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
591 if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
593 bInsertTimestamp = TRUE;
598 pHeader_802_11->Sequence = pAd->Sequence++;
599 if (pAd->Sequence >0xfff)
602 // Before radar detection done, mgmt frame can not be sent but probe req
603 // Because we need to use probe req to trigger driver to send probe req in passive scan
604 if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
605 && (pAd->CommonCfg.bIEEE80211H == 1)
606 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
608 DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
609 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
610 return (NDIS_STATUS_FAILURE);
614 // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
615 // should always has only one ohysical buffer, and the whole frame size equals
616 // to the first scatter buffer size
619 // Initialize TX Descriptor
620 // For inter-frame gap, the number is for this frame and next frame
621 // For MLME rate, we will fix as 2Mb to match other vendor's implement
623 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
624 if (pMacEntry == NULL)
626 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
627 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
631 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
632 bInsertTimestamp, FALSE, bAckRequired, FALSE,
633 0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE),
634 pMacEntry->MaxHTPhyMode.field.MCS, 0,
635 (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
636 IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
639 // Now do hardware-depened kick out.
640 HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen);
642 // Make sure to release MGMT ring resource
643 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
644 return NDIS_STATUS_SUCCESS;
648 /********************************************************************************
650 New DeQueue Procedures.
652 ********************************************************************************/
654 #define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \
656 if (bIntContext == FALSE) \
657 RTMP_IRQ_LOCK((lock), IrqFlags); \
660 #define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \
662 if (bIntContext == FALSE) \
663 RTMP_IRQ_UNLOCK((lock), IrqFlags); \
667 ========================================================================
668 Tx Path design algorithm:
669 Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal),
670 Specific Packet Type. Following show the classification rule and policy for each kinds of packets.
671 Classification Rule=>
672 Multicast: (*addr1 & 0x01) == 0x01
673 Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc.
674 11N Rate : If peer support HT
675 (1).AMPDU -- If TXBA is negotiated.
676 (2).AMSDU -- If AMSDU is capable for both peer and ourself.
677 *). AMSDU can embedded in a AMPDU, but now we didn't support it.
678 (3).Normal -- Other packets which send as 11n rate.
680 B/G Rate : If peer is b/g only.
681 (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6
682 (2).Normal -- Other packets which send as b/g rate.
684 The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
686 Classified Packet Handle Rule=>
688 No ACK, //pTxBlk->bAckRequired = FALSE;
689 No WMM, //pTxBlk->bWMM = FALSE;
690 No piggyback, //pTxBlk->bPiggyBack = FALSE;
691 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
692 Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use
693 the same policy to handle it.
694 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
697 No piggyback, //pTxBlk->bPiggyBack = FALSE;
709 ========================================================================
711 static UCHAR TxPktClassification(
712 IN RTMP_ADAPTER *pAd,
713 IN PNDIS_PACKET pPacket)
715 UCHAR TxFrameType = TX_UNKOWN_FRAME;
717 MAC_TABLE_ENTRY *pMacEntry = NULL;
718 BOOLEAN bHTRate = FALSE;
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 else if (IS_HT_RATE(pMacEntry))
733 { // it's a 11n capable packet
735 // Depends on HTPhyMode to check if the peer support the HTRate transmission.
736 // Currently didn't support A-MSDU embedded in A-MPDU
738 if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE))
739 TxFrameType = TX_LEGACY_FRAME;
740 #ifdef UAPSD_AP_SUPPORT
741 else if (RTMP_GET_PACKET_EOSP(pPacket))
742 TxFrameType = TX_LEGACY_FRAME;
743 #endif // UAPSD_AP_SUPPORT //
744 else if((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0)
745 return TX_AMPDU_FRAME;
746 else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED))
747 return TX_AMSDU_FRAME;
749 TxFrameType = TX_LEGACY_FRAME;
752 { // it's a legacy b/g packet.
753 if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) &&
754 (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) &&
755 (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
756 { // if peer support Ralink Aggregation, we use it.
757 TxFrameType = TX_RALINK_FRAME;
761 TxFrameType = TX_LEGACY_FRAME;
765 // Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU.
766 if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) && (TxFrameType == TX_LEGACY_FRAME))
767 TxFrameType = TX_FRAG_FRAME;
773 BOOLEAN RTMP_FillTxBlkInfo(
774 IN RTMP_ADAPTER *pAd,
777 PACKET_INFO PacketInfo;
778 PNDIS_PACKET pPacket;
779 PMAC_TABLE_ENTRY pMacEntry = NULL;
781 pPacket = pTxBlk->pPacket;
782 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
784 pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket);
785 pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket);
786 pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket);
787 pTxBlk->FrameGap = IFS_HTTXOP; // ASIC determine Frame Gap
789 if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket))
790 TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame);
792 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame);
794 // Default to clear this flag
795 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS);
798 if (pTxBlk->Wcid == MCAST_WCID)
800 pTxBlk->pMacEntry = NULL;
802 #ifdef MCAST_RATE_SPECIFIC
803 PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket);
804 if (((*pDA & 0x01) == 0x01) && (*pDA != 0xff))
805 pTxBlk->pTransmit = &pAd->CommonCfg.MCastPhyMode;
807 #endif // MCAST_RATE_SPECIFIC //
808 pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
811 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); // AckRequired = FALSE, when broadcast packet in Adhoc mode.
812 //TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate);
813 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag);
814 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
815 if (RTMP_GET_PACKET_MOREDATA(pPacket))
817 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
823 pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
824 pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode;
826 pMacEntry = pTxBlk->pMacEntry;
829 // For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK.
830 if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK)
831 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
833 TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired);
836 // If support WMM, enable it.
838 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
841 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
842 CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))
844 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;
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);
864 if ( (IS_HT_RATE(pMacEntry) == FALSE) &&
865 (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE)))
866 { // Currently piggy-back only support when peer is operate in b/g mode.
867 TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack);
870 if (RTMP_GET_PACKET_MOREDATA(pPacket))
872 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
874 #ifdef UAPSD_AP_SUPPORT
875 if (RTMP_GET_PACKET_EOSP(pPacket))
877 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP);
879 #endif // UAPSD_AP_SUPPORT //
881 else if (pTxBlk->TxFrameType == TX_FRAG_FRAME)
883 TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag);
886 pMacEntry->DebugTxCount++;
893 BOOLEAN CanDoAggregateTransmit(
894 IN RTMP_ADAPTER *pAd,
895 IN NDIS_PACKET *pPacket,
899 //printk("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType);
901 if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
904 if (RTMP_GET_PACKET_DHCP(pPacket) ||
905 RTMP_GET_PACKET_EAPOL(pPacket) ||
906 RTMP_GET_PACKET_WAI(pPacket))
909 if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) &&
910 ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100)))
911 { // For AMSDU, allow the packets with total length < max-amsdu size
915 if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) &&
916 (pTxBlk->TxPacketList.Number == 2))
917 { // For RALINK-Aggregation, allow two frames in one batch.
921 if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP
929 ========================================================================
932 To do the enqueue operation and extract the first item of waiting
933 list. If a number of available shared memory segments could meet
934 the request of extracted item, the extracted item will be fragmented
935 into shared memory segments.
938 pAd Pointer to our adapter
939 pQueue Pointer to Waiting Queue
944 IRQL = DISPATCH_LEVEL
948 ========================================================================
950 VOID RTMPDeQueuePacket(
951 IN PRTMP_ADAPTER pAd,
952 IN BOOLEAN bIntContext,
953 IN UCHAR QIdx, /* BulkOutPipeId */
954 IN UCHAR Max_Tx_Packets)
956 PQUEUE_ENTRY pEntry = NULL;
957 PNDIS_PACKET pPacket;
958 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
960 PQUEUE_HEADER pQueue;
961 ULONG FreeNumber[NUM_OF_TX_RING];
962 UCHAR QueIdx, sQIdx, eQIdx;
963 unsigned long IrqFlags = 0;
964 BOOLEAN hasTxDesc = FALSE;
970 if (QIdx == NUM_OF_TX_RING)
973 //PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA)
974 eQIdx = 3; // 4 ACs, start from 0.
978 sQIdx = eQIdx = QIdx;
981 for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++)
985 RT28XX_START_DEQUEUE(pAd, QueIdx, IrqFlags);
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)
1006 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1010 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
1013 if (FreeNumber[QueIdx] <= 5)
1015 // free Tx(QueIdx) resources
1016 RTMPFreeTXDUponTxDmaDone(pAd, QueIdx);
1017 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
1020 // probe the Queue Head
1021 pQueue = &pAd->TxSwQueue[QueIdx];
1022 if ((pEntry = pQueue->Head) == NULL)
1024 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1029 NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK));
1030 pTxBlk->QueIdx = QueIdx;
1032 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
1034 // Early check to make sure we have enoguh Tx Resource.
1035 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
1038 pAd->PrivateInfo.TxRingFullCnt++;
1040 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1045 pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
1046 pEntry = RemoveHeadQueue(pQueue);
1047 pTxBlk->TotalFrameNum++;
1048 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
1049 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
1050 pTxBlk->pPacket = pPacket;
1051 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
1053 if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME)
1055 // Enhance SW Aggregation Mechanism
1056 if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType))
1058 InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
1059 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1064 if((pEntry = pQueue->Head) == NULL)
1067 // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation.
1068 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
1069 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
1070 hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
1071 if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE))
1074 //Remove the packet from the TxSwQueue and insert into pTxBlk
1075 pEntry = RemoveHeadQueue(pQueue);
1077 pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
1078 pTxBlk->TotalFrameNum++;
1079 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
1080 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
1081 InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
1084 if (pTxBlk->TxPacketList.Number == 1)
1085 pTxBlk->TxFrameType = TX_LEGACY_FRAME;
1089 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1092 Count += pTxBlk->TxPacketList.Number;
1094 // Do HardTransmit now.
1095 Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
1098 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
1099 // static rate also need NICUpdateFifoStaCounters() function.
1100 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
1101 NICUpdateFifoStaCounters(pAd);
1105 RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
1109 RTUSBKickBulkOut(pAd);
1117 ========================================================================
1119 Routine Description:
1120 Calculates the duration which is required to transmit out frames
1121 with given size and specified rate.
1124 pAd Pointer to our adapter
1126 Size Frame size in units of byte
1129 Duration number in units of usec
1131 IRQL = PASSIVE_LEVEL
1132 IRQL = DISPATCH_LEVEL
1136 ========================================================================
1138 USHORT RTMPCalcDuration(
1139 IN PRTMP_ADAPTER pAd,
1145 if (Rate < RATE_FIRST_OFDM_RATE) // CCK
1147 if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED))
1148 Duration = 96; // 72+24 preamble+plcp
1150 Duration = 192; // 144+48 preamble+plcp
1152 Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]);
1153 if ((Size << 4) % RateIdTo500Kbps[Rate])
1156 else if (Rate <= RATE_LAST_OFDM_RATE)// OFDM rates
1158 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
1159 Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
1160 if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
1165 Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
1168 return (USHORT)Duration;
1173 ========================================================================
1175 Routine Description:
1176 Calculates the duration which is required to transmit out frames
1177 with given size and specified rate.
1180 pTxWI Pointer to head of each MPDU to HW.
1181 Ack Setting for Ack requirement bit
1182 Fragment Setting for Fragment bit
1183 RetryMode Setting for retry mode
1184 Ifs Setting for IFS gap
1185 Rate Setting for transmit rate
1186 Service Setting for service
1188 TxPreamble Short or Long preamble when using CCK rates
1189 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1194 IRQL = PASSIVE_LEVEL
1195 IRQL = DISPATCH_LEVEL
1197 See also : BASmartHardTransmit() !!!
1199 ========================================================================
1202 IN PRTMP_ADAPTER pAd,
1203 IN PTXWI_STRUC pOutTxWI,
1206 IN BOOLEAN InsTimestamp,
1209 IN BOOLEAN NSeq, // HW new a sequence.
1218 IN HTTRANSMIT_SETTING *pTransmit)
1220 PMAC_TABLE_ENTRY pMac = NULL;
1224 if (WCID < MAX_LEN_OF_MAC_TABLE)
1225 pMac = &pAd->MacTab.Content[WCID];
1228 // Always use Long preamble before verifiation short preamble functionality works well.
1229 // Todo: remove the following line if short preamble functionality works
1231 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1232 NdisZeroMemory(&TxWI, TXWI_SIZE);
1237 pTxWI->CFACK = CFACK;
1238 pTxWI->TS= InsTimestamp;
1239 pTxWI->AMPDU = AMPDU;
1241 pTxWI->txop= Txopmode;
1244 // John tune the performace with Intel Client in 20 MHz performance
1245 BASize = pAd->CommonCfg.TxBASize;
1249 pTxWI->BAWinSize = BASize;
1250 pTxWI->ShortGI = pTransmit->field.ShortGI;
1251 pTxWI->STBC = pTransmit->field.STBC;
1253 pTxWI->WirelessCliID = WCID;
1254 pTxWI->MPDUtotalByteCount = Length;
1255 pTxWI->PacketId = PID;
1257 // If CCK or OFDM, BW must be 20
1258 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1260 pTxWI->MCS = pTransmit->field.MCS;
1261 pTxWI->PHYMODE = pTransmit->field.MODE;
1262 pTxWI->CFACK = CfAck;
1266 if (pAd->CommonCfg.bMIMOPSEnable)
1268 if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1270 // Dynamic MIMO Power Save Mode
1273 else if (pMac->MmpsMode == MMPS_STATIC)
1275 // Static MIMO Power Save Mode
1276 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1283 //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;
1284 if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled))
1286 pTxWI->MpduDensity = 7;
1290 pTxWI->MpduDensity = pMac->MpduDensity;
1294 pTxWI->PacketId = pTxWI->MCS;
1295 NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC));
1299 VOID RTMPWriteTxWI_Data(
1300 IN PRTMP_ADAPTER pAd,
1301 IN OUT PTXWI_STRUC pTxWI,
1304 HTTRANSMIT_SETTING *pTransmit;
1305 PMAC_TABLE_ENTRY pMacEntry;
1310 pTransmit = pTxBlk->pTransmit;
1311 pMacEntry = pTxBlk->pMacEntry;
1315 // Always use Long preamble before verifiation short preamble functionality works well.
1316 // Todo: remove the following line if short preamble functionality works
1318 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1319 NdisZeroMemory(pTxWI, TXWI_SIZE);
1321 pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1322 pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1323 pTxWI->txop = pTxBlk->FrameGap;
1325 pTxWI->WirelessCliID = pTxBlk->Wcid;
1327 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1328 pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
1330 // If CCK or OFDM, BW must be 20
1331 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1332 pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
1334 // John tune the performace with Intel Client in 20 MHz performance
1335 BASize = pAd->CommonCfg.TxBASize;
1336 if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry))
1338 UCHAR RABAOriIdx = 0; //The RA's BA Originator table index.
1340 RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
1341 BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1344 pTxWI->TxBF = pTransmit->field.TxBF;
1345 pTxWI->BAWinSize = BASize;
1346 pTxWI->ShortGI = pTransmit->field.ShortGI;
1347 pTxWI->STBC = pTransmit->field.STBC;
1349 pTxWI->MCS = pTransmit->field.MCS;
1350 pTxWI->PHYMODE = pTransmit->field.MODE;
1354 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1356 // Dynamic MIMO Power Save Mode
1359 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1361 // Static MIMO Power Save Mode
1362 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1369 if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled))
1371 pTxWI->MpduDensity = 7;
1375 pTxWI->MpduDensity = pMacEntry->MpduDensity;
1380 // for rate adapation
1381 pTxWI->PacketId = pTxWI->MCS;
1385 VOID RTMPWriteTxWI_Cache(
1386 IN PRTMP_ADAPTER pAd,
1387 IN OUT PTXWI_STRUC pTxWI,
1390 PHTTRANSMIT_SETTING pTransmit;
1391 PMAC_TABLE_ENTRY pMacEntry;
1396 pMacEntry = pTxBlk->pMacEntry;
1397 pTransmit = pTxBlk->pTransmit;
1399 if (pMacEntry->bAutoTxRateSwitch)
1401 pTxWI->txop = IFS_HTTXOP;
1403 // If CCK or OFDM, BW must be 20
1404 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1405 pTxWI->ShortGI = pTransmit->field.ShortGI;
1406 pTxWI->STBC = pTransmit->field.STBC;
1408 pTxWI->MCS = pTransmit->field.MCS;
1409 pTxWI->PHYMODE = pTransmit->field.MODE;
1411 // set PID for TxRateSwitching
1412 pTxWI->PacketId = pTransmit->field.MCS;
1415 pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE);
1418 if (pAd->CommonCfg.bMIMOPSEnable)
1420 // MIMO Power Save Mode
1421 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1423 // Dynamic MIMO Power Save Mode
1426 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1428 // Static MIMO Power Save Mode
1429 if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7))
1438 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1444 ========================================================================
1446 Routine Description:
1447 Calculates the duration which is required to transmit out frames
1448 with given size and specified rate.
1451 pTxD Pointer to transmit descriptor
1452 Ack Setting for Ack requirement bit
1453 Fragment Setting for Fragment bit
1454 RetryMode Setting for retry mode
1455 Ifs Setting for IFS gap
1456 Rate Setting for transmit rate
1457 Service Setting for service
1459 TxPreamble Short or Long preamble when using CCK rates
1460 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1465 IRQL = PASSIVE_LEVEL
1466 IRQL = DISPATCH_LEVEL
1468 ========================================================================
1470 VOID RTMPWriteTxDescriptor(
1471 IN PRTMP_ADAPTER pAd,
1477 // Always use Long preamble before verifiation short preamble functionality works well.
1478 // Todo: remove the following line if short preamble functionality works
1480 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1482 pTxD->WIV = (bWIV) ? 1: 0;
1483 pTxD->QSEL= (QueueSEL);
1484 if (pAd->bGenOneHCCA == TRUE)
1485 pTxD->QSEL= FIFO_HCCA;
1490 // should be called only when -
1491 // 1. MEADIA_CONNECTED
1492 // 2. AGGREGATION_IN_USED
1493 // 3. Fragmentation not in used
1494 // 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible
1495 BOOLEAN TxFrameIsAggregatible(
1496 IN PRTMP_ADAPTER pAd,
1497 IN PUCHAR pPrevAddr1,
1501 // can't aggregate EAPOL (802.1x) frame
1502 if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1505 // can't aggregate multicast/broadcast frame
1506 if (p8023hdr[0] & 0x01)
1509 if (INFRA_ON(pAd)) // must be unicast to AP
1511 else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA
1519 ========================================================================
1521 Routine Description:
1522 Check the MSDU Aggregation policy
1523 1.HT aggregation is A-MSDU
1524 2.legaacy rate aggregation is software aggregation by Ralink.
1532 ========================================================================
1534 BOOLEAN PeerIsAggreOn(
1535 IN PRTMP_ADAPTER pAd,
1537 IN PMAC_TABLE_ENTRY pMacEntry)
1539 ULONG AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
1541 if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags))
1543 if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX)
1548 #ifdef AGGREGATION_SUPPORT
1549 if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
1550 { // legacy Ralink Aggregation support
1553 #endif // AGGREGATION_SUPPORT //
1562 ========================================================================
1564 Routine Description:
1565 Check and fine the packet waiting in SW queue with highest priority
1568 pAd Pointer to our adapter
1571 pQueue Pointer to Waiting Queue
1573 IRQL = DISPATCH_LEVEL
1577 ========================================================================
1579 PQUEUE_HEADER RTMPCheckTxSwQueue(
1580 IN PRTMP_ADAPTER pAd,
1586 Number = pAd->TxSwQueue[QID_AC_BK].Number
1587 + pAd->TxSwQueue[QID_AC_BE].Number
1588 + pAd->TxSwQueue[QID_AC_VI].Number
1589 + pAd->TxSwQueue[QID_AC_VO].Number
1590 + pAd->TxSwQueue[QID_HCCA].Number;
1592 if (pAd->TxSwQueue[QID_AC_VO].Head != NULL)
1594 *pQueIdx = QID_AC_VO;
1595 return (&pAd->TxSwQueue[QID_AC_VO]);
1597 else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL)
1599 *pQueIdx = QID_AC_VI;
1600 return (&pAd->TxSwQueue[QID_AC_VI]);
1602 else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL)
1604 *pQueIdx = QID_AC_BE;
1605 return (&pAd->TxSwQueue[QID_AC_BE]);
1607 else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL)
1609 *pQueIdx = QID_AC_BK;
1610 return (&pAd->TxSwQueue[QID_AC_BK]);
1612 else if (pAd->TxSwQueue[QID_HCCA].Head != NULL)
1614 *pQueIdx = QID_HCCA;
1615 return (&pAd->TxSwQueue[QID_HCCA]);
1618 // No packet pending in Tx Sw queue
1619 *pQueIdx = QID_AC_BK;
1625 BOOLEAN RTMPFreeTXDUponTxDmaDone(
1626 IN PRTMP_ADAPTER pAd,
1629 PRTMP_TX_RING pTxRing;
1631 PNDIS_PACKET pPacket;
1633 TXD_STRUC TxD, *pOriTxD;
1635 BOOLEAN bReschedule = FALSE;
1638 ASSERT(QueIdx < NUM_OF_TX_RING);
1639 pTxRing = &pAd->TxRing[QueIdx];
1641 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF, &pTxRing->TxDmaIdx);
1642 while (pTxRing->TxSwFreeIdx != pTxRing->TxDmaIdx)
1644 // static rate also need NICUpdateFifoStaCounters() function.
1645 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
1646 NICUpdateFifoStaCounters(pAd);
1648 /* Note : If (pAd->ate.bQATxStart == TRUE), we will never reach here. */
1650 pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
1652 NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC));
1657 /*====================================================================*/
1659 pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket;
1662 #ifdef CONFIG_5VT_ENHANCE
1663 if (RTMP_GET_PACKET_5VT(pPacket))
1664 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE);
1666 #endif // CONFIG_5VT_ENHANCE //
1667 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
1668 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1670 //Always assign pNdisPacket as NULL after clear
1671 pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket = NULL;
1673 pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket;
1675 ASSERT(pPacket == NULL);
1678 #ifdef CONFIG_5VT_ENHANCE
1679 if (RTMP_GET_PACKET_5VT(pPacket))
1680 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE);
1682 #endif // CONFIG_5VT_ENHANCE //
1683 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
1684 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1686 //Always assign pNextNdisPacket as NULL after clear
1687 pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL;
1689 /*====================================================================*/
1691 pAd->RalinkCounters.TransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0);
1692 pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++;
1693 INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE);
1694 /* get tx_tdx_idx again */
1695 RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &pTxRing->TxDmaIdx);
1697 NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC));
1707 ========================================================================
1709 Routine Description:
1710 Process TX Rings DMA Done interrupt, running in DPC level
1713 Adapter Pointer to our adapter
1718 IRQL = DISPATCH_LEVEL
1720 ========================================================================
1722 BOOLEAN RTMPHandleTxRingDmaDoneInterrupt(
1723 IN PRTMP_ADAPTER pAd,
1724 IN INT_SOURCE_CSR_STRUC TxRingBitmap)
1726 unsigned long IrqFlags;
1727 BOOLEAN bReschedule = FALSE;
1729 // Make sure Tx ring resource won't be used by other threads
1731 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1733 if (TxRingBitmap.field.Ac0DmaDone)
1734 bReschedule = RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BE);
1736 if (TxRingBitmap.field.HccaDmaDone)
1737 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_HCCA);
1739 if (TxRingBitmap.field.Ac3DmaDone)
1740 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VO);
1742 if (TxRingBitmap.field.Ac2DmaDone)
1743 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VI);
1745 if (TxRingBitmap.field.Ac1DmaDone)
1746 bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BK);
1748 // Make sure to release Tx ring resource
1749 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1751 // Dequeue outgoing frames from TxSwQueue[] and process it
1752 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1759 ========================================================================
1761 Routine Description:
1762 Process MGMT ring DMA done interrupt, running in DPC level
1765 pAd Pointer to our adapter
1770 IRQL = DISPATCH_LEVEL
1774 ========================================================================
1776 VOID RTMPHandleMgmtRingDmaDoneInterrupt(
1777 IN PRTMP_ADAPTER pAd)
1780 PNDIS_PACKET pPacket;
1782 PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing;
1784 NdisAcquireSpinLock(&pAd->MgmtRingLock);
1786 RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pMgmtRing->TxDmaIdx);
1787 while (pMgmtRing->TxSwFreeIdx!= pMgmtRing->TxDmaIdx)
1790 pTxD = (PTXD_STRUC) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa);
1792 pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket;
1797 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
1798 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1800 pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket = NULL;
1802 pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket;
1805 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
1806 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1808 pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket = NULL;
1809 INC_RING_INDEX(pMgmtRing->TxSwFreeIdx, MGMT_RING_SIZE);
1811 NdisReleaseSpinLock(&pAd->MgmtRingLock);
1817 ========================================================================
1819 Routine Description:
1821 Adapter Pointer to our adapter. Dequeue all power safe delayed braodcast frames after beacon.
1823 IRQL = DISPATCH_LEVEL
1825 ========================================================================
1827 VOID RTMPHandleTBTTInterrupt(
1828 IN PRTMP_ADAPTER pAd)
1831 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1839 ========================================================================
1841 Routine Description:
1843 Adapter Pointer to our adapter. Rewrite beacon content before next send-out.
1845 IRQL = DISPATCH_LEVEL
1847 ========================================================================
1849 VOID RTMPHandlePreTBTTInterrupt(
1850 IN PRTMP_ADAPTER pAd)
1853 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1855 DBGPRINT(RT_DEBUG_TRACE, ("RTMPHandlePreTBTTInterrupt...\n"));
1862 VOID RTMPHandleRxCoherentInterrupt(
1863 IN PRTMP_ADAPTER pAd)
1865 WPDMA_GLO_CFG_STRUC GloCfg;
1869 DBGPRINT(RT_DEBUG_TRACE, ("====> pAd is NULL, return.\n"));
1873 DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPHandleRxCoherentInterrupt \n"));
1875 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG , &GloCfg.word);
1877 GloCfg.field.EnTXWriteBackDDONE = 0;
1878 GloCfg.field.EnableRxDMA = 0;
1879 GloCfg.field.EnableTxDMA = 0;
1880 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
1882 RTMPRingCleanUp(pAd, QID_AC_BE);
1883 RTMPRingCleanUp(pAd, QID_AC_BK);
1884 RTMPRingCleanUp(pAd, QID_AC_VI);
1885 RTMPRingCleanUp(pAd, QID_AC_VO);
1886 RTMPRingCleanUp(pAd, QID_HCCA);
1887 RTMPRingCleanUp(pAd, QID_MGMT);
1888 RTMPRingCleanUp(pAd, QID_RX);
1890 RTMPEnableRxTx(pAd);
1892 DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPHandleRxCoherentInterrupt \n"));
1897 ========================================================================
1899 Routine Description:
1900 Suspend MSDU transmission
1903 pAd Pointer to our adapter
1910 ========================================================================
1912 VOID RTMPSuspendMsduTransmission(
1913 IN PRTMP_ADAPTER pAd)
1915 DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n"));
1919 // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
1920 // use Lowbound as R66 value on ScanNextChannel(...)
1922 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue);
1924 // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)
1925 RTMPSetAGCInitValue(pAd, BW_20);
1927 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1932 ========================================================================
1934 Routine Description:
1935 Resume MSDU transmission
1938 pAd Pointer to our adapter
1943 IRQL = DISPATCH_LEVEL
1947 ========================================================================
1949 VOID RTMPResumeMsduTransmission(
1950 IN PRTMP_ADAPTER pAd)
1952 DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
1954 // After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value
1955 // R66 should not be 0
1956 if (pAd->BbpTuning.R66CurrentValue == 0)
1958 pAd->BbpTuning.R66CurrentValue = 0x38;
1959 DBGPRINT_ERR(("RTMPResumeMsduTransmission, R66CurrentValue=0...\n"));
1962 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue);
1964 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1965 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1969 UINT deaggregate_AMSDU_announce(
1970 IN PRTMP_ADAPTER pAd,
1971 PNDIS_PACKET pPacket,
1976 USHORT SubFrameSize;
1977 PHEADER_802_3 pAMSDUsubheader;
1979 UCHAR Header802_3[14];
1981 PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP;
1982 PNDIS_PACKET pClonePacket;
1988 while (DataSize > LENGTH_802_3)
1993 pAMSDUsubheader = (PHEADER_802_3)pData;
1994 PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8);
1995 SubFrameSize = PayloadSize + LENGTH_802_3;
1998 if ((DataSize < SubFrameSize) || (PayloadSize > 1518 ))
2003 pPayload = pData + LENGTH_802_3;
2005 pSA = pData + MAC_ADDR_LEN;
2007 // convert to 802.3 header
2008 CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP);
2010 if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) )
2012 // avoid local heap overflow, use dyanamic allocation
2013 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
2014 memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize);
2015 Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize;
2016 WpaEAPOLKeyAction(pAd, Elem);
2021 if (pRemovedLLCSNAP)
2023 pPayload -= LENGTH_802_3;
2024 PayloadSize += LENGTH_802_3;
2025 NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3);
2029 pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
2032 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket));
2036 // A-MSDU has padding to multiple of 4 including subframe header.
2037 // align SubFrameSize up to multiple of 4
2038 SubFrameSize = (SubFrameSize+3)&(~0x3);
2041 if (SubFrameSize > 1528 || SubFrameSize < 32)
2046 if (DataSize > SubFrameSize)
2048 pData += SubFrameSize;
2049 DataSize -= SubFrameSize;
2058 // finally release original rx packet
2059 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
2065 UINT BA_Reorder_AMSDU_Annnounce(
2066 IN PRTMP_ADAPTER pAd,
2067 IN PNDIS_PACKET pPacket)
2073 pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
2074 DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
2076 nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
2083 ==========================================================================
2085 Look up the MAC address in the MAC table. Return NULL if not found.
2087 pEntry - pointer to the MAC entry; NULL is not found
2088 ==========================================================================
2090 MAC_TABLE_ENTRY *MacTableLookup(
2091 IN PRTMP_ADAPTER pAd,
2095 MAC_TABLE_ENTRY *pEntry = NULL;
2097 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
2098 pEntry = pAd->MacTab.Hash[HashIdx];
2100 while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh))
2102 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
2107 pEntry = pEntry->pNext;
2113 MAC_TABLE_ENTRY *MacTableInsertEntry(
2114 IN PRTMP_ADAPTER pAd,
2117 IN BOOLEAN CleanAll)
2121 MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
2124 if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
2129 if (pAd->StaCfg.BssType == BSS_INFRA)
2132 // allocate one MAC entry
2133 NdisAcquireSpinLock(&pAd->MacTabLock);
2134 for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++) // skip entry#0 so that "entry index == AID" for fast lookup
2136 // pick up the first available vacancy
2137 if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
2138 (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
2139 (pAd->MacTab.Content[i].ValidAsApCli== FALSE) &&
2140 (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
2143 pEntry = &pAd->MacTab.Content[i];
2144 if (CleanAll == TRUE)
2146 pEntry->MaxSupportedRate = RATE_11;
2147 pEntry->CurrTxRate = RATE_11;
2148 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
2149 pEntry->PairwiseKey.KeyLen = 0;
2150 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
2154 pEntry->ValidAsCLI = TRUE;
2155 pEntry->ValidAsWDS = FALSE;
2156 pEntry->ValidAsApCli = FALSE;
2157 pEntry->ValidAsMesh = FALSE;
2158 pEntry->ValidAsDls = FALSE;
2162 pEntry->bIAmBadAtheros = FALSE;
2164 pEntry->CMTimerRunning = FALSE;
2165 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
2166 pEntry->RSNIE_Len = 0;
2167 NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
2168 pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
2170 if (pEntry->ValidAsMesh)
2171 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH);
2172 else if (pEntry->ValidAsApCli)
2173 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI);
2174 else if (pEntry->ValidAsWDS)
2175 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS);
2177 pEntry->apidx = apidx;
2181 pEntry->AuthMode = pAd->StaCfg.AuthMode;
2182 pEntry->WepStatus = pAd->StaCfg.WepStatus;
2183 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
2185 AsicRemovePairwiseKeyEntry(pAd, pEntry->apidx, (UCHAR)i);
2190 pEntry->GTKState = REKEY_NEGOTIATING;
2191 pEntry->PairwiseKey.KeyLen = 0;
2192 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
2195 if ((pAd->OpMode == OPMODE_STA) &&
2196 (pAd->StaCfg.BssType == BSS_ADHOC))
2197 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
2200 pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
2202 pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
2203 COPY_MAC_ADDR(pEntry->Addr, pAddr);
2204 pEntry->Sst = SST_NOT_AUTH;
2205 pEntry->AuthState = AS_NOT_AUTH;
2206 pEntry->Aid = (USHORT)i; //0;
2207 pEntry->CapabilityInfo = 0;
2208 pEntry->PsMode = PWR_ACTIVE;
2209 pEntry->PsQIdleCount = 0;
2210 pEntry->NoDataIdleCount = 0;
2211 pEntry->ContinueTxFailCnt = 0;
2212 InitializeQueueHeader(&pEntry->PsQueue);
2215 pAd->MacTab.Size ++;
2216 // Add this entry into ASIC RX WCID search table
2217 RT28XX_STA_ENTRY_ADD(pAd, pEntry);
2221 DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size));
2226 // add this MAC entry into HASH table
2229 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
2230 if (pAd->MacTab.Hash[HashIdx] == NULL)
2232 pAd->MacTab.Hash[HashIdx] = pEntry;
2236 pCurrEntry = pAd->MacTab.Hash[HashIdx];
2237 while (pCurrEntry->pNext != NULL)
2238 pCurrEntry = pCurrEntry->pNext;
2239 pCurrEntry->pNext = pEntry;
2243 NdisReleaseSpinLock(&pAd->MacTabLock);
2248 ==========================================================================
2250 Delete a specified client from MAC table
2251 ==========================================================================
2253 BOOLEAN MacTableDeleteEntry(
2254 IN PRTMP_ADAPTER pAd,
2259 MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
2262 if (wcid >= MAX_LEN_OF_MAC_TABLE)
2265 NdisAcquireSpinLock(&pAd->MacTabLock);
2267 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
2268 pEntry = &pAd->MacTab.Content[wcid];
2270 if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh
2273 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
2276 // Delete this entry from ASIC on-chip WCID Table
2277 RT28XX_STA_ENTRY_MAC_RESET(pAd, wcid);
2279 // free resources of BA
2280 BASessionTearDownALL(pAd, pEntry->Aid);
2283 pProbeEntry = pAd->MacTab.Hash[HashIdx];
2284 ASSERT(pProbeEntry);
2289 if (pProbeEntry == pEntry)
2291 if (pPrevEntry == NULL)
2293 pAd->MacTab.Hash[HashIdx] = pEntry->pNext;
2297 pPrevEntry->pNext = pEntry->pNext;
2302 pPrevEntry = pProbeEntry;
2303 pProbeEntry = pProbeEntry->pNext;
2304 } while (pProbeEntry);
2307 ASSERT(pProbeEntry != NULL);
2309 RT28XX_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
2312 if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
2314 RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
2315 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
2319 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
2320 pAd->MacTab.Size --;
2321 DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size));
2325 printk("\n%s: Impossible Wcid = %d !!!!!\n", __func__, wcid);
2329 NdisReleaseSpinLock(&pAd->MacTabLock);
2331 //Reset operating mode when no Sta.
2332 if (pAd->MacTab.Size == 0)
2334 pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
2336 AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/);
2338 // edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet
2339 // Set MAC register value according operation mode
2340 RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_UPDATE_PROTECT, NULL, 0);
2349 ==========================================================================
2351 This routine reset the entire MAC table. All packets pending in
2352 the power-saving queues are freed here.
2353 ==========================================================================
2356 IN PRTMP_ADAPTER pAd)
2360 DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
2361 //NdisAcquireSpinLock(&pAd->MacTabLock);
2363 for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
2366 RT28XX_STA_ENTRY_MAC_RESET(pAd, i);
2368 if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
2370 // free resources of BA
2371 BASessionTearDownALL(pAd, i);
2373 pAd->MacTab.Content[i].ValidAsCLI = FALSE;
2378 NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6);
2379 RT28XX_STA_ENTRY_MAC_RESET(pAd, i);
2382 //AsicDelWcidTab(pAd, i);
2390 ==========================================================================
2393 IRQL = DISPATCH_LEVEL
2395 ==========================================================================
2398 IN PRTMP_ADAPTER pAd,
2399 IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
2401 IN USHORT CapabilityInfo,
2403 IN USHORT ListenIntv)
2405 COPY_MAC_ADDR(AssocReq->Addr, pAddr);
2406 // Add mask to support 802.11b mode only
2407 AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request
2408 AssocReq->Timeout = Timeout;
2409 AssocReq->ListenIntv = ListenIntv;
2414 ==========================================================================
2417 IRQL = DISPATCH_LEVEL
2419 ==========================================================================
2421 VOID DisassocParmFill(
2422 IN PRTMP_ADAPTER pAd,
2423 IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
2427 COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
2428 DisassocReq->Reason = Reason;
2433 ========================================================================
2435 Routine Description:
2436 Check the out going frame, if this is an DHCP or ARP datagram
2437 will be duplicate another frame at low data rate transmit.
2440 pAd Pointer to our adapter
2441 pPacket Pointer to outgoing Ndis frame
2444 TRUE To be duplicate at Low data rate transmit. (1mb)
2447 IRQL = DISPATCH_LEVEL
2451 MAC header + IP Header + UDP Header
2455 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
2457 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
2460 port 0x43 means Bootstrap Protocol, server.
2461 Port 0x44 means Bootstrap Protocol, client.
2463 ========================================================================
2466 BOOLEAN RTMPCheckDHCPFrame(
2467 IN PRTMP_ADAPTER pAd,
2468 IN PNDIS_PACKET pPacket)
2470 PACKET_INFO PacketInfo;
2471 ULONG NumberOfBytesRead = 0;
2472 ULONG CurrentOffset = 0;
2473 PVOID pVirtualAddress = NULL;
2474 UINT NdisBufferLength;
2477 UCHAR ByteOffset36 = 0;
2478 UCHAR ByteOffset38 = 0;
2479 BOOLEAN ReadFirstParm = TRUE;
2481 RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength);
2483 NumberOfBytesRead += NdisBufferLength;
2484 pSrc = (PUCHAR) pVirtualAddress;
2485 Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
2488 // Check DHCP & BOOTP protocol
2490 while (NumberOfBytesRead <= PacketInfo.TotalPacketLength)
2492 if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE))
2494 CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength);
2495 ByteOffset36 = *(pSrc + CurrentOffset);
2496 ReadFirstParm = FALSE;
2499 if (NumberOfBytesRead >= 37)
2501 CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength);
2502 ByteOffset38 = *(pSrc + CurrentOffset);
2509 // Check for DHCP & BOOTP protocol
2510 if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43))
2513 // 2054 (hex 0806) for ARP datagrams
2514 // if this packet is not ARP datagrams, then do nothing
2515 // ARP datagrams will also be duplicate at 1mb broadcast frames
2517 if (Protocol != 0x0806 )
2525 BOOLEAN RTMPCheckEtherType(
2526 IN PRTMP_ADAPTER pAd,
2527 IN PNDIS_PACKET pPacket)
2533 UINT16 srcPort, dstPort;
2534 BOOLEAN status = TRUE;
2537 pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
2538 pktLen = GET_OS_PKT_LEN(pPacket);
2542 RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
2544 // get Ethernet protocol field
2545 TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13];
2547 pSrcBuf += LENGTH_802_3; // Skip the Ethernet Header.
2549 if (TypeLen <= 1500)
2550 { // 802.3, 802.3 LLC
2552 DestMAC(6) + SrcMAC(6) + Lenght(2) +
2553 DSAP(1) + SSAP(1) + Control(1) +
2554 if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
2555 => + SNAP (5, OriginationID(3) + etherType(2))
2557 if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03)
2559 Sniff2BytesFromNdisBuffer(pSrcBuf, 6, &Byte0, &Byte1);
2560 RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
2561 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2562 pSrcBuf += 8; // Skip this LLC/SNAP header
2566 //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.
2570 // If it's a VLAN packet, get the real Type/Length field.
2571 if (TypeLen == 0x8100)
2573 /* 0x8100 means VLAN packets */
2575 /* Dest. MAC Address (6-bytes) +
2576 Source MAC Address (6-bytes) +
2577 Length/Type = 802.1Q Tag Type (2-byte) +
2578 Tag Control Information (2-bytes) +
2579 Length / Type (2-bytes) +
2580 data payload (0-n bytes) +
2582 Frame Check Sequence (4-bytes) */
2584 RTMP_SET_PACKET_VLAN(pPacket, 1);
2585 Sniff2BytesFromNdisBuffer(pSrcBuf, 2, &Byte0, &Byte1);
2586 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2588 pSrcBuf += 4; // Skip the VLAN Header.
2595 ASSERT((pktLen > 34));
2596 if (*(pSrcBuf + 9) == 0x11)
2598 ASSERT((pktLen > 34)); // 14 for ethernet header, 20 for IP header
2600 pSrcBuf += 20; // Skip the IP header
2601 srcPort = OS_NTOHS(*((UINT16 *)pSrcBuf));
2602 dstPort = OS_NTOHS(*((UINT16 *)(pSrcBuf +2)));
2604 if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44))
2605 { //It's a BOOTP/DHCP packet
2606 RTMP_SET_PACKET_DHCP(pPacket, 1);
2614 RTMP_SET_PACKET_DHCP(pPacket, 1);
2620 RTMP_SET_PACKET_EAPOL(pPacket, 1);
2634 VOID Update_Rssi_Sample(
2635 IN PRTMP_ADAPTER pAd,
2636 IN RSSI_SAMPLE *pRssi,
2637 IN PRXWI_STRUC pRxWI)
2639 CHAR rssi0 = pRxWI->RSSI0;
2640 CHAR rssi1 = pRxWI->RSSI1;
2641 CHAR rssi2 = pRxWI->RSSI2;
2645 pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0);
2646 pRssi->AvgRssi0X8 = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
2647 pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
2652 pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1);
2653 pRssi->AvgRssi1X8 = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
2654 pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
2659 pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2);
2660 pRssi->AvgRssi2X8 = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
2661 pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
2667 // Normal legacy Rx packet indication
2668 VOID Indicate_Legacy_Packet(
2669 IN PRTMP_ADAPTER pAd,
2671 IN UCHAR FromWhichBSSID)
2673 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2674 UCHAR Header802_3[LENGTH_802_3];
2676 // 1. get 802.3 Header
2678 // a. pointer pRxBlk->pData to payload
2679 // b. modify pRxBlk->DataSize
2680 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2682 if (pRxBlk->DataSize > MAX_RX_PKT_LEN)
2686 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2691 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
2694 if (pAd->CommonCfg.bDisableReordering == 0)
2696 PBA_REC_ENTRY pBAEntry;
2698 UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID;
2699 UCHAR TID = pRxBlk->pRxWI->TID;
2702 #define REORDERING_PACKET_TIMEOUT ((100 * HZ)/1000) // system ticks -- 100 ms
2704 if (Wcid < MAX_LEN_OF_MAC_TABLE)
2706 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
2709 pBAEntry = &pAd->BATable.BARecEntry[Idx];
2710 // update last rx time
2711 NdisGetSystemUpTime(&Now32);
2712 if ((pBAEntry->list.qlen > 0) &&
2713 RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
2716 printk("Indicate_Legacy_Packet():flush reordering_timeout_mpdus! RxWI->Flags=%d, pRxWI.TID=%d, RxD->AMPDU=%d!\n", pRxBlk->Flags, pRxBlk->pRxWI->TID, pRxBlk->RxD.AMPDU);
2717 hex_dump("Dump the legacy Packet:", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), 64);
2718 ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
2725 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2728 // pass this 802.3 packet to upper layer or forward this packet to WM directly
2730 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
2734 // Normal, AMPDU or AMSDU
2735 VOID CmmRxnonRalinkFrameIndicate(
2736 IN PRTMP_ADAPTER pAd,
2738 IN UCHAR FromWhichBSSID)
2740 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
2742 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2746 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
2749 Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2753 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
2759 VOID CmmRxRalinkFrameIndicate(
2760 IN PRTMP_ADAPTER pAd,
2761 IN MAC_TABLE_ENTRY *pEntry,
2763 IN UCHAR FromWhichBSSID)
2765 UCHAR Header802_3[LENGTH_802_3];
2767 UINT16 Payload1Size, Payload2Size;
2769 PNDIS_PACKET pPacket2 = NULL;
2773 Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8);
2775 if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize))
2777 /* skip two byte MSDU2 len */
2779 pRxBlk->DataSize -= 2;
2784 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2788 // get 802.3 Header and remove LLC
2789 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2791 ASSERT(pRxBlk->pRxPacket);
2793 // Ralink Aggregation frame
2794 pAd->RalinkCounters.OneSecRxAggregationCount ++;
2795 Payload1Size = pRxBlk->DataSize - Msdu2Size;
2796 Payload2Size = Msdu2Size - LENGTH_802_3;
2798 pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
2800 pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID);
2805 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2809 // update payload size of 1st packet
2810 pRxBlk->DataSize = Payload1Size;
2811 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2813 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID);
2817 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
2822 #define RESET_FRAGFRAME(_fragFrame) \
2824 _fragFrame.RxSize = 0; \
2825 _fragFrame.Sequence = 0; \
2826 _fragFrame.LastFrag = 0; \
2827 _fragFrame.Flags = 0; \
2831 PNDIS_PACKET RTMPDeFragmentDataFrame(
2832 IN PRTMP_ADAPTER pAd,
2835 PHEADER_802_11 pHeader = pRxBlk->pHeader;
2836 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2837 UCHAR *pData = pRxBlk->pData;
2838 USHORT DataSize = pRxBlk->DataSize;
2839 PNDIS_PACKET pRetPacket = NULL;
2840 UCHAR *pFragBuffer = NULL;
2841 BOOLEAN bReassDone = FALSE;
2842 UCHAR HeaderRoom = 0;
2847 HeaderRoom = pData - (UCHAR *)pHeader;
2849 // Re-assemble the fragmented packets
2850 if (pHeader->Frag == 0) // Frag. Number is 0 : First frag or only one pkt
2852 // the first pkt of fragment, record it.
2853 if (pHeader->FC.MoreFrag)
2855 ASSERT(pAd->FragFrame.pFragPacket);
2856 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2857 pAd->FragFrame.RxSize = DataSize + HeaderRoom;
2858 NdisMoveMemory(pFragBuffer, pHeader, pAd->FragFrame.RxSize);
2859 pAd->FragFrame.Sequence = pHeader->Sequence;
2860 pAd->FragFrame.LastFrag = pHeader->Frag; // Should be 0
2861 ASSERT(pAd->FragFrame.LastFrag == 0);
2862 goto done; // end of processing this frame
2865 else //Middle & End of fragment
2867 if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
2868 (pHeader->Frag != (pAd->FragFrame.LastFrag + 1)))
2870 // Fragment is not the same sequence or out of fragment number order
2871 // Reset Fragment control blk
2872 RESET_FRAGFRAME(pAd->FragFrame);
2873 DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n"));
2874 goto done; // give up this frame
2876 else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE)
2878 // Fragment frame is too large, it exeeds the maximum frame size.
2879 // Reset Fragment control blk
2880 RESET_FRAGFRAME(pAd->FragFrame);
2881 DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
2882 goto done; // give up this frame
2886 // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.
2887 // In this case, we will dropt it.
2889 if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H)))
2891 DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag));
2892 goto done; // give up this frame
2895 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2897 // concatenate this fragment into the re-assembly buffer
2898 NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize);
2899 pAd->FragFrame.RxSize += DataSize;
2900 pAd->FragFrame.LastFrag = pHeader->Frag; // Update fragment number
2903 if (pHeader->FC.MoreFrag == FALSE)
2910 // always release rx fragmented packet
2911 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2913 // return defragmented packet if packet is reassembled completely
2914 // otherwise return NULL
2917 PNDIS_PACKET pNewFragPacket;
2919 // allocate a new packet buffer for fragment
2920 pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
2924 pRetPacket = pAd->FragFrame.pFragPacket;
2925 pAd->FragFrame.pFragPacket = pNewFragPacket;
2926 pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
2927 pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom;
2928 pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
2929 pRxBlk->pRxPacket = pRetPacket;
2933 RESET_FRAGFRAME(pAd->FragFrame);
2941 VOID Indicate_AMSDU_Packet(
2942 IN PRTMP_ADAPTER pAd,
2944 IN UCHAR FromWhichBSSID)
2948 update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
2949 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
2950 nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize);
2953 VOID Indicate_EAPOL_Packet(
2954 IN PRTMP_ADAPTER pAd,
2956 IN UCHAR FromWhichBSSID)
2958 MAC_TABLE_ENTRY *pEntry = NULL;
2961 pEntry = &pAd->MacTab.Content[BSSID_WCID];
2962 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
2968 DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
2970 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2975 #define BCN_TBTT_OFFSET 64 //defer 64 us
2976 VOID ReSyncBeaconTime(
2977 IN PRTMP_ADAPTER pAd)
2983 Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
2985 pAd->TbttTickCount++;
2988 // The updated BeaconInterval Value will affect Beacon Interval after two TBTT
2989 // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
2991 if (Offset == (BCN_TBTT_OFFSET-2))
2993 BCN_TIME_CFG_STRUC csr;
2994 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2995 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; // ASIC register in units of 1/16 TU = 64us
2996 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
3000 if (Offset == (BCN_TBTT_OFFSET-1))
3002 BCN_TIME_CFG_STRUC csr;
3004 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
3005 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU
3006 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);