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 u8 SNAP_802_1H[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
31 u8 SNAP_BRIDGE_TUNNEL[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
33 /* Add Cisco Aironet SNAP heade for CCX2 support */
34 u8 SNAP_AIRONET[] = { 0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00 };
35 u8 CKIP_LLC_SNAP[] = { 0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02 };
36 u8 EAPOL_LLC_SNAP[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e };
37 u8 EAPOL[] = { 0x88, 0x8e };
38 u8 TPID[] = { 0x81, 0x00 }; /* VLAN related */
40 u8 IPX[] = { 0x81, 0x37 };
41 u8 APPLE_TALK[] = { 0x80, 0xf3 };
43 u8 RateIdToPlcpSignal[12] = {
44 0, /* RATE_1 */ 1, /* RATE_2 */ 2, /* RATE_5_5 */ 3, /* RATE_11 *//* see BBP spec */
45 11, /* RATE_6 */ 15, /* RATE_9 */ 10, /* RATE_12 */ 14, /* RATE_18 *//* see IEEE802.11a-1999 p.14 */
46 9, /* RATE_24 */ 13, /* RATE_36 */ 8, /* RATE_48 */ 12 /* RATE_54 */
47 }; /* see IEEE802.11a-1999 p.14 */
49 u8 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 u8 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 */
62 u8 RxwiMCSToOfdmRate[12] = {
63 RATE_6, RATE_9, RATE_12, RATE_18,
64 RATE_24, RATE_36, RATE_48, RATE_54, /* OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3 */
65 4, 5, 6, 7, /* OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7 */
69 { "1Mbps", "2Mbps", "5.5Mbps", "11Mbps", "06Mbps", "09Mbps", "12Mbps",
70 "18Mbps", "24Mbps", "36Mbps", "48Mbps", "54Mbps", "MM-0", "MM-1", "MM-2", "MM-3",
71 "MM-4", "MM-5", "MM-6", "MM-7", "MM-8", "MM-9", "MM-10", "MM-11", "MM-12", "MM-13",
72 "MM-14", "MM-15", "MM-32", "ee1", "ee2", "ee3" };
75 { CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS - 1, CW_MIN_IN_BITS - 2 };
76 /*u8 default_cwmax[]={CW_MAX_IN_BITS, CW_MAX_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1}; */
77 u8 default_sta_aifsn[] = { 3, 7, 2, 2 };
79 u8 MapUserPriorityToAccessCategory[8] =
80 { QID_AC_BE, QID_AC_BK, QID_AC_BK, QID_AC_BE, QID_AC_VI, QID_AC_VI,
81 QID_AC_VO, QID_AC_VO };
84 ========================================================================
87 API for MLME to transmit management frame to AP (BSS Mode)
88 or station (IBSS Mode)
91 pAd Pointer to our adapter
92 pData Pointer to the outgoing 802.11 frame
93 Length Size of outgoing management frame
101 IRQL = DISPATCH_LEVEL
105 ========================================================================
107 int MiniportMMRequest(struct rt_rtmp_adapter *pAd,
108 u8 QueIdx, u8 *pData, u32 Length)
111 int Status = NDIS_STATUS_SUCCESS;
112 unsigned long FreeNum;
113 u8 rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; /*RTMP_HW_HDR_LEN]; */
115 unsigned long IrqFlags = 0;
117 #endif /* RTMP_MAC_PCI // */
118 BOOLEAN bUseDataQ = FALSE;
121 ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
123 if ((QueIdx & MGMT_USE_QUEUE_FLAG) == MGMT_USE_QUEUE_FLAG) {
125 QueIdx &= (~MGMT_USE_QUEUE_FLAG);
128 /* 2860C use Tx Ring */
129 IrqState = pAd->irq_disabled;
130 if (pAd->MACVersion == 0x28600100) {
131 QueIdx = (bUseDataQ == TRUE ? QueIdx : 3);
134 if (bUseDataQ && (!IrqState))
135 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
136 #endif /* RTMP_MAC_PCI // */
139 /* Reset is in progress, stop immediately */
140 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
142 fRTMP_ADAPTER_HALT_IN_PROGRESS |
143 fRTMP_ADAPTER_NIC_NOT_EXIST)
144 || !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) {
145 Status = NDIS_STATUS_FAILURE;
148 /* Check Free priority queue */
149 /* Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing. */
152 retryCnt = MAX_DATAMM_RETRY;
153 /* free Tx(QueIdx) resources */
154 RTMPFreeTXDUponTxDmaDone(pAd, QueIdx);
155 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
157 #endif /* RTMP_MAC_PCI // */
159 FreeNum = GET_MGMTRING_FREENO(pAd);
163 /* We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870 */
164 NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE));
166 RTMPAllocateNdisPacket(pAd, &pPacket,
168 (TXINFO_SIZE + TXWI_SIZE),
170 if (Status != NDIS_STATUS_SUCCESS) {
171 DBGPRINT(RT_DEBUG_WARN,
172 ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
175 /*pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; */
176 /*pAd->CommonCfg.MlmeRate = RATE_2; */
181 MlmeDataHardTransmit(pAd, QueIdx, pPacket);
184 #endif /* RTMP_MAC_PCI // */
185 Status = MlmeHardTransmit(pAd, QueIdx, pPacket);
186 if (Status == NDIS_STATUS_SUCCESS)
189 RTMPFreeNdisPacket(pAd, pPacket);
191 pAd->RalinkCounters.MgmtRingFullCount++;
195 DBGPRINT(RT_DEBUG_TRACE,
196 ("retryCnt %d\n", retryCnt));
198 DBGPRINT(RT_DEBUG_ERROR,
199 ("Qidx(%d), not enough space in DataRing, MgmtRingFullCount=%ld!\n",
205 #endif /* RTMP_MAC_PCI // */
206 DBGPRINT(RT_DEBUG_ERROR,
207 ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n",
209 pAd->RalinkCounters.MgmtRingFullCount));
211 } while (retryCnt > 0);
214 if (bUseDataQ && (!IrqState))
215 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
216 #endif /* RTMP_MAC_PCI // */
222 ========================================================================
225 Copy frame from waiting queue into relative ring buffer and set
226 appropriate ASIC register to kick hardware transmit function
229 pAd Pointer to our adapter
230 pBuffer Pointer to memory of outgoing frame
231 Length Size of outgoing management frame
239 IRQL = DISPATCH_LEVEL
243 ========================================================================
245 int MlmeHardTransmit(struct rt_rtmp_adapter *pAd,
246 u8 QueIdx, void *pPacket)
248 struct rt_packet_info PacketInfo;
251 struct rt_header_802_11 * pHeader_802_11;
253 if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
255 return NDIS_STATUS_FAILURE;
258 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
259 if (pSrcBufVA == NULL)
260 return NDIS_STATUS_FAILURE;
262 pHeader_802_11 = (struct rt_header_802_11 *) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE);
265 if (pAd->MACVersion == 0x28600100)
266 return MlmeHardTransmitTxRing(pAd, QueIdx, pPacket);
268 #endif /* RTMP_MAC_PCI // */
269 return MlmeHardTransmitMgmtRing(pAd, QueIdx, pPacket);
273 int MlmeHardTransmitMgmtRing(struct rt_rtmp_adapter *pAd,
274 u8 QueIdx, void *pPacket)
276 struct rt_packet_info PacketInfo;
279 struct rt_header_802_11 * pHeader_802_11;
280 BOOLEAN bAckRequired, bInsertTimestamp;
282 struct rt_txwi * pFirstTxWI;
283 struct rt_mac_table_entry *pMacEntry = NULL;
286 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
288 /* Make sure MGMT ring resource won't be used by other threads */
289 RTMP_SEM_LOCK(&pAd->MgmtRingLock);
290 if (pSrcBufVA == NULL) {
291 /* The buffer shouldn't be NULL */
292 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
293 return NDIS_STATUS_FAILURE;
297 /* outgoing frame always wakeup PHY to prevent frame lost */
298 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
299 AsicForceWakeup(pAd, TRUE);
302 pFirstTxWI = (struct rt_txwi *) (pSrcBufVA + TXINFO_SIZE);
303 pHeader_802_11 = (struct rt_header_802_11 *) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); /*TXWI_SIZE); */
305 if (pHeader_802_11->Addr1[0] & 0x01) {
306 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
308 MlmeRate = pAd->CommonCfg.MlmeRate;
311 /* Verify Mlme rate for a / g bands. */
312 if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) /* 11A band */
315 if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
316 (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) {
317 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
321 /* Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode. */
322 if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED
323 || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) {
324 if (pAd->LatchRfRegs.Channel > 14)
325 pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
327 pAd->CommonCfg.MlmeTransmit.field.MODE = 0;
332 /* Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE) */
333 /* Snice it's been set to 0 while on MgtMacHeaderInit */
334 /* By the way this will cause frame to be send on PWR_SAVE failed. */
336 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE; /* (pAd->StaCfg.Psm == PWR_SAVE); */
339 /* In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame */
340 /* Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD */
341 /* if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL)) */
343 if ((pHeader_802_11->FC.SubType == SUBTYPE_ACTION) ||
344 ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
345 ((pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL) ||
346 (pHeader_802_11->FC.SubType == SUBTYPE_NULL_FUNC)))) {
347 if (pAd->StaCfg.Psm == PWR_SAVE)
348 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
350 pHeader_802_11->FC.PwrMgmt =
351 pAd->CommonCfg.bAPSDForcePowerSave;
355 bInsertTimestamp = FALSE;
356 if (pHeader_802_11->FC.Type == BTYPE_CNTL) /* must be PS-POLL */
358 /*Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue. */
359 if ((pAd->OpMode == OPMODE_STA)
360 && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL)) {
361 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
363 bAckRequired = FALSE;
364 } else /* BTYPE_MGMT or BTYPE_DATA(must be NULL frame) */
366 /*pAd->Sequence++; */
367 /*pHeader_802_11->Sequence = pAd->Sequence; */
369 if (pHeader_802_11->Addr1[0] & 0x01) /* MULTICAST, BROADCAST */
371 bAckRequired = FALSE;
372 pHeader_802_11->Duration = 0;
375 pHeader_802_11->Duration =
376 RTMPCalcDuration(pAd, MlmeRate, 14);
377 if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
378 && (pHeader_802_11->FC.Type == BTYPE_MGMT)) {
379 bInsertTimestamp = TRUE;
380 bAckRequired = FALSE; /* Disable ACK to prevent retry 0x1f for Probe Response */
382 if ((pHeader_802_11->FC.SubType ==
384 && (pHeader_802_11->FC.Type == BTYPE_MGMT)) {
385 bAckRequired = FALSE; /* Disable ACK to prevent retry 0x1f for Probe Request */
390 pHeader_802_11->Sequence = pAd->Sequence++;
391 if (pAd->Sequence > 0xfff)
394 /* Before radar detection done, mgmt frame can not be sent but probe req */
395 /* Because we need to use probe req to trigger driver to send probe req in passive scan */
396 if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
397 && (pAd->CommonCfg.bIEEE80211H == 1)
398 && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)) {
399 DBGPRINT(RT_DEBUG_ERROR,
400 ("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
402 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
403 return (NDIS_STATUS_FAILURE);
407 /* fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET */
408 /* should always has only one physical buffer, and the whole frame size equals */
409 /* to the first scatter buffer size */
412 /* Initialize TX Descriptor */
413 /* For inter-frame gap, the number is for this frame and next frame */
414 /* For MLME rate, we will fix as 2Mb to match other vendor's implement */
415 /* pAd->CommonCfg.MlmeTransmit.field.MODE = 1; */
417 /* management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not. */
420 if (pMacEntry == NULL) {
421 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp,
422 FALSE, bAckRequired, FALSE, 0, RESERVED_WCID,
423 (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID, 0,
424 (u8)pAd->CommonCfg.MlmeTransmit.field.MCS,
425 IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
427 /* dont use low rate to send QoS Null data frame */
428 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
429 bInsertTimestamp, FALSE, bAckRequired, FALSE,
431 (SrcBufLen - TXINFO_SIZE - TXWI_SIZE),
432 pMacEntry->MaxHTPhyMode.field.MCS, 0,
433 (u8)pMacEntry->MaxHTPhyMode.field.MCS,
434 IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
437 /* Now do hardware-depened kick out. */
438 HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen);
440 /* Make sure to release MGMT ring resource */
442 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
443 return NDIS_STATUS_SUCCESS;
446 /********************************************************************************
448 New DeQueue Procedures.
450 ********************************************************************************/
452 #define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \
454 if (bIntContext == FALSE) \
455 RTMP_IRQ_LOCK((lock), IrqFlags); \
458 #define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \
460 if (bIntContext == FALSE) \
461 RTMP_IRQ_UNLOCK((lock), IrqFlags); \
465 ========================================================================
466 Tx Path design algorithm:
467 Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal),
468 Specific Packet Type. Following show the classification rule and policy for each kinds of packets.
469 Classification Rule=>
470 Multicast: (*addr1 & 0x01) == 0x01
471 Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc.
472 11N Rate : If peer support HT
473 (1).AMPDU -- If TXBA is negotiated.
474 (2).AMSDU -- If AMSDU is capable for both peer and ourself.
475 *). AMSDU can embedded in a AMPDU, but now we didn't support it.
476 (3).Normal -- Other packets which send as 11n rate.
478 B/G Rate : If peer is b/g only.
479 (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6
480 (2).Normal -- Other packets which send as b/g rate.
482 The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
484 Classified Packet Handle Rule=>
486 No ACK, //pTxBlk->bAckRequired = FALSE;
487 No WMM, //pTxBlk->bWMM = FALSE;
488 No piggyback, //pTxBlk->bPiggyBack = FALSE;
489 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
490 Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use
491 the same policy to handle it.
492 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
495 No piggyback, //pTxBlk->bPiggyBack = FALSE;
507 ========================================================================
509 static u8 TxPktClassification(struct rt_rtmp_adapter *pAd, void *pPacket)
511 u8 TxFrameType = TX_UNKOWN_FRAME;
513 struct rt_mac_table_entry *pMacEntry = NULL;
514 BOOLEAN bHTRate = FALSE;
516 Wcid = RTMP_GET_PACKET_WCID(pPacket);
517 if (Wcid == MCAST_WCID) { /* Handle for RA is Broadcast/Multicast Address. */
518 return TX_MCAST_FRAME;
520 /* Handle for unicast packets */
521 pMacEntry = &pAd->MacTab.Content[Wcid];
522 if (RTMP_GET_PACKET_LOWRATE(pPacket)) { /* It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame */
523 TxFrameType = TX_LEGACY_FRAME;
524 } else if (IS_HT_RATE(pMacEntry)) { /* it's a 11n capable packet */
526 /* Depends on HTPhyMode to check if the peer support the HTRate transmission. */
527 /* Currently didn't support A-MSDU embedded in A-MPDU */
529 if (RTMP_GET_PACKET_MOREDATA(pPacket)
530 || (pMacEntry->PsMode == PWR_SAVE))
531 TxFrameType = TX_LEGACY_FRAME;
532 else if ((pMacEntry->
533 TXBAbitmap & (1 << (RTMP_GET_PACKET_UP(pPacket)))) !=
535 return TX_AMPDU_FRAME;
536 else if (CLIENT_STATUS_TEST_FLAG
537 (pMacEntry, fCLIENT_STATUS_AMSDU_INUSED))
538 return TX_AMSDU_FRAME;
540 TxFrameType = TX_LEGACY_FRAME;
541 } else { /* it's a legacy b/g packet. */
542 if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) && (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)))) { /* if peer support Ralink Aggregation, we use it. */
543 TxFrameType = TX_RALINK_FRAME;
545 TxFrameType = TX_LEGACY_FRAME;
549 /* Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU. */
550 if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1)
551 && (TxFrameType == TX_LEGACY_FRAME))
552 TxFrameType = TX_FRAG_FRAME;
557 BOOLEAN RTMP_FillTxBlkInfo(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
559 struct rt_packet_info PacketInfo;
561 struct rt_mac_table_entry *pMacEntry = NULL;
563 pPacket = pTxBlk->pPacket;
564 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader,
567 pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket);
568 pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket);
569 pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket);
570 pTxBlk->FrameGap = IFS_HTTXOP; /* ASIC determine Frame Gap */
572 if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket))
573 TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame);
575 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame);
577 /* Default to clear this flag */
578 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS);
580 if (pTxBlk->Wcid == MCAST_WCID) {
581 pTxBlk->pMacEntry = NULL;
584 &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
587 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); /* AckRequired = FALSE, when broadcast packet in Adhoc mode. */
588 /*TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate); */
589 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag);
590 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
591 if (RTMP_GET_PACKET_MOREDATA(pPacket)) {
592 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
596 pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
597 pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode;
599 pMacEntry = pTxBlk->pMacEntry;
601 /* For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK. */
602 if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK)
603 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
605 TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired);
607 if ((pAd->OpMode == OPMODE_STA) &&
609 (RX_FILTER_TEST_FLAG(pAd, fRX_FILTER_ACCEPT_PROMISCUOUS))) {
610 if (pAd->CommonCfg.PSPXlink)
611 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
617 /* If support WMM, enable it. */
618 if (OPSTATUS_TEST_FLAG
619 (pAd, fOP_STATUS_WMM_INUSED)
620 && CLIENT_STATUS_TEST_FLAG(pMacEntry,
621 fCLIENT_STATUS_WMM_CAPABLE))
622 TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM);
624 /* if (pAd->StaCfg.bAutoTxRateSwitch) */
625 /* TX_BLK_SET_FLAG(pTxBlk, fTX_AutoRateSwitch); */
629 if (pTxBlk->TxFrameType == TX_LEGACY_FRAME) {
630 if ((RTMP_GET_PACKET_LOWRATE(pPacket)) || ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1))) { /* Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate. */
632 &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
634 /* Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it??? */
635 if (IS_HT_STA(pTxBlk->pMacEntry) &&
636 (CLIENT_STATUS_TEST_FLAG
637 (pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET))
638 && ((pAd->CommonCfg.bRdg == TRUE)
639 && CLIENT_STATUS_TEST_FLAG(pMacEntry,
640 fCLIENT_STATUS_RDG_CAPABLE)))
642 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
643 TX_BLK_SET_FLAG(pTxBlk,
648 if ((IS_HT_RATE(pMacEntry) == FALSE) && (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE))) { /* Currently piggy-back only support when peer is operate in b/g mode. */
649 TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack);
652 if (RTMP_GET_PACKET_MOREDATA(pPacket)) {
653 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
655 } else if (pTxBlk->TxFrameType == TX_FRAG_FRAME) {
656 TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag);
659 pMacEntry->DebugTxCount++;
665 BOOLEAN CanDoAggregateTransmit(struct rt_rtmp_adapter *pAd,
666 char * pPacket, struct rt_tx_blk *pTxBlk)
669 /*DBGPRINT(RT_DEBUG_TRACE, ("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType)); */
671 if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
674 if (RTMP_GET_PACKET_DHCP(pPacket) ||
675 RTMP_GET_PACKET_EAPOL(pPacket) || RTMP_GET_PACKET_WAI(pPacket))
678 if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) && ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket)) > (RX_BUFFER_AGGRESIZE - 100))) { /* For AMSDU, allow the packets with total length < max-amsdu size */
682 if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) && (pTxBlk->TxPacketList.Number == 2)) { /* For RALINK-Aggregation, allow two frames in one batch. */
686 if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) /* must be unicast to AP */
694 ========================================================================
697 To do the enqueue operation and extract the first item of waiting
698 list. If a number of available shared memory segments could meet
699 the request of extracted item, the extracted item will be fragmented
700 into shared memory segments.
703 pAd Pointer to our adapter
704 pQueue Pointer to Waiting Queue
709 IRQL = DISPATCH_LEVEL
713 ========================================================================
715 void RTMPDeQueuePacket(struct rt_rtmp_adapter *pAd, IN BOOLEAN bIntContext, u8 QIdx, /* BulkOutPipeId */
718 struct rt_queue_entry *pEntry = NULL;
720 int Status = NDIS_STATUS_SUCCESS;
722 struct rt_queue_header *pQueue;
723 unsigned long FreeNumber[NUM_OF_TX_RING];
724 u8 QueIdx, sQIdx, eQIdx;
725 unsigned long IrqFlags = 0;
726 BOOLEAN hasTxDesc = FALSE;
727 struct rt_tx_blk TxBlk;
728 struct rt_tx_blk *pTxBlk;
730 if (QIdx == NUM_OF_TX_RING) {
732 eQIdx = 3; /* 4 ACs, start from 0. */
734 sQIdx = eQIdx = QIdx;
737 for (QueIdx = sQIdx; QueIdx <= eQIdx; QueIdx++) {
740 RTMP_START_DEQUEUE(pAd, QueIdx, IrqFlags);
745 (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |
746 fRTMP_ADAPTER_RADIO_OFF |
747 fRTMP_ADAPTER_RESET_IN_PROGRESS |
748 fRTMP_ADAPTER_HALT_IN_PROGRESS |
749 fRTMP_ADAPTER_NIC_NOT_EXIST)))) {
750 RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
754 if (Count >= Max_Tx_Packets)
757 DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
758 if (&pAd->TxSwQueue[QueIdx] == NULL) {
759 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext,
764 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
766 if (FreeNumber[QueIdx] <= 5) {
767 /* free Tx(QueIdx) resources */
768 RTMPFreeTXDUponTxDmaDone(pAd, QueIdx);
770 GET_TXRING_FREENO(pAd, QueIdx);
772 #endif /* RTMP_MAC_PCI // */
774 /* probe the Queue Head */
775 pQueue = &pAd->TxSwQueue[QueIdx];
776 if ((pEntry = pQueue->Head) == NULL) {
777 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext,
783 NdisZeroMemory((u8 *)pTxBlk, sizeof(struct rt_tx_blk));
784 /*InitializeQueueHeader(&pTxBlk->TxPacketList); // Didn't need it because we already memzero it. */
785 pTxBlk->QueIdx = QueIdx;
787 pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
789 /* Early check to make sure we have enoguh Tx Resource. */
791 RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk,
795 pAd->PrivateInfo.TxRingFullCnt++;
797 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext,
803 pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
804 pEntry = RemoveHeadQueue(pQueue);
805 pTxBlk->TotalFrameNum++;
806 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); /* The real fragment number maybe vary */
807 pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
808 pTxBlk->pPacket = pPacket;
809 InsertTailQueue(&pTxBlk->TxPacketList,
810 PACKET_TO_QUEUE_ENTRY(pPacket));
812 if (pTxBlk->TxFrameType == TX_RALINK_FRAME
813 || pTxBlk->TxFrameType == TX_AMSDU_FRAME) {
814 /* Enhance SW Aggregation Mechanism */
815 if (NEED_QUEUE_BACK_FOR_AGG
816 (pAd, QueIdx, FreeNumber[QueIdx],
817 pTxBlk->TxFrameType)) {
818 InsertHeadQueue(pQueue,
819 PACKET_TO_QUEUE_ENTRY
821 DEQUEUE_UNLOCK(&pAd->irq_lock,
822 bIntContext, IrqFlags);
827 if ((pEntry = pQueue->Head) == NULL)
830 /* For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation. */
831 pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
833 GET_TXRING_FREENO(pAd, QueIdx);
835 RTMP_HAS_ENOUGH_FREE_DESC(pAd,
840 if ((hasTxDesc == FALSE)
842 (CanDoAggregateTransmit
843 (pAd, pPacket, pTxBlk) == FALSE))
846 /*Remove the packet from the TxSwQueue and insert into pTxBlk */
847 pEntry = RemoveHeadQueue(pQueue);
849 pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
850 pTxBlk->TotalFrameNum++;
851 pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); /* The real fragment number maybe vary */
852 pTxBlk->TotalFrameLen +=
853 GET_OS_PKT_LEN(pPacket);
854 InsertTailQueue(&pTxBlk->TxPacketList,
855 PACKET_TO_QUEUE_ENTRY
859 if (pTxBlk->TxPacketList.Number == 1)
860 pTxBlk->TxFrameType = TX_LEGACY_FRAME;
863 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
864 #endif /* RTMP_MAC_USB // */
865 Count += pTxBlk->TxPacketList.Number;
867 /* Do HardTransmit now. */
868 Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
871 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
872 /* static rate also need NICUpdateFifoStaCounters() function. */
873 /*if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */
874 NICUpdateFifoStaCounters(pAd);
875 #endif /* RTMP_MAC_PCI // */
879 RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
883 RTUSBKickBulkOut(pAd);
884 #endif /* RTMP_MAC_USB // */
890 ========================================================================
893 Calculates the duration which is required to transmit out frames
894 with given size and specified rate.
897 pAd Pointer to our adapter
899 Size Frame size in units of byte
902 Duration number in units of usec
905 IRQL = DISPATCH_LEVEL
909 ========================================================================
911 u16 RTMPCalcDuration(struct rt_rtmp_adapter *pAd, u8 Rate, unsigned long Size)
913 unsigned long Duration = 0;
915 if (Rate < RATE_FIRST_OFDM_RATE) /* CCK */
918 && OPSTATUS_TEST_FLAG(pAd,
919 fOP_STATUS_SHORT_PREAMBLE_INUSED))
920 Duration = 96; /* 72+24 preamble+plcp */
922 Duration = 192; /* 144+48 preamble+plcp */
924 Duration += (u16)((Size << 4) / RateIdTo500Kbps[Rate]);
925 if ((Size << 4) % RateIdTo500Kbps[Rate])
927 } else if (Rate <= RATE_LAST_OFDM_RATE) /* OFDM rates */
929 Duration = 20 + 6; /* 16+4 preamble+plcp + Signal Extension */
931 4 * (u16)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
932 if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
934 } else /*mimo rate */
936 Duration = 20 + 6; /* 16+4 preamble+plcp + Signal Extension */
939 return (u16)Duration;
943 ========================================================================
946 Calculates the duration which is required to transmit out frames
947 with given size and specified rate.
950 pTxWI Pointer to head of each MPDU to HW.
951 Ack Setting for Ack requirement bit
952 Fragment Setting for Fragment bit
953 RetryMode Setting for retry mode
954 Ifs Setting for IFS gap
955 Rate Setting for transmit rate
956 Service Setting for service
958 TxPreamble Short or Long preamble when using CCK rates
959 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
965 IRQL = DISPATCH_LEVEL
967 See also : BASmartHardTransmit() !!!
969 ========================================================================
971 void RTMPWriteTxWI(struct rt_rtmp_adapter *pAd, struct rt_txwi * pOutTxWI, IN BOOLEAN FRAG, IN BOOLEAN CFACK, IN BOOLEAN InsTimestamp, IN BOOLEAN AMPDU, IN BOOLEAN Ack, IN BOOLEAN NSeq, /* HW new a sequence. */
974 unsigned long Length,
979 IN BOOLEAN CfAck, IN HTTRANSMIT_SETTING * pTransmit)
981 struct rt_mac_table_entry *pMac = NULL;
983 struct rt_txwi * pTxWI;
985 if (WCID < MAX_LEN_OF_MAC_TABLE)
986 pMac = &pAd->MacTab.Content[WCID];
989 /* Always use Long preamble before verifiation short preamble functionality works well. */
990 /* Todo: remove the following line if short preamble functionality works */
992 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
993 NdisZeroMemory(&TxWI, TXWI_SIZE);
998 pTxWI->CFACK = CFACK;
999 pTxWI->TS = InsTimestamp;
1000 pTxWI->AMPDU = AMPDU;
1002 pTxWI->txop = Txopmode;
1005 /* John tune the performace with Intel Client in 20 MHz performance */
1006 BASize = pAd->CommonCfg.TxBASize;
1007 if (pAd->MACVersion == 0x28720200) {
1014 pTxWI->BAWinSize = BASize;
1015 pTxWI->ShortGI = pTransmit->field.ShortGI;
1016 pTxWI->STBC = pTransmit->field.STBC;
1018 pTxWI->WirelessCliID = WCID;
1019 pTxWI->MPDUtotalByteCount = Length;
1020 pTxWI->PacketId = PID;
1022 /* If CCK or OFDM, BW must be 20 */
1024 (pTransmit->field.MODE <=
1025 MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1027 pTxWI->MCS = pTransmit->field.MCS;
1028 pTxWI->PHYMODE = pTransmit->field.MODE;
1029 pTxWI->CFACK = CfAck;
1032 if (pAd->CommonCfg.bMIMOPSEnable) {
1033 if ((pMac->MmpsMode == MMPS_DYNAMIC)
1034 && (pTransmit->field.MCS > 7)) {
1035 /* Dynamic MIMO Power Save Mode */
1037 } else if (pMac->MmpsMode == MMPS_STATIC) {
1038 /* Static MIMO Power Save Mode */
1039 if (pTransmit->field.MODE >= MODE_HTMIX
1040 && pTransmit->field.MCS > 7) {
1046 /*pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0; */
1047 if (pMac->bIAmBadAtheros
1048 && (pMac->WepStatus != Ndis802_11WEPDisabled)) {
1049 pTxWI->MpduDensity = 7;
1051 pTxWI->MpduDensity = pMac->MpduDensity;
1055 pTxWI->PacketId = pTxWI->MCS;
1056 NdisMoveMemory(pOutTxWI, &TxWI, sizeof(struct rt_txwi));
1059 void RTMPWriteTxWI_Data(struct rt_rtmp_adapter *pAd,
1060 struct rt_txwi * pTxWI, struct rt_tx_blk *pTxBlk)
1062 HTTRANSMIT_SETTING *pTransmit;
1063 struct rt_mac_table_entry *pMacEntry;
1068 pTransmit = pTxBlk->pTransmit;
1069 pMacEntry = pTxBlk->pMacEntry;
1072 /* Always use Long preamble before verifiation short preamble functionality works well. */
1073 /* Todo: remove the following line if short preamble functionality works */
1075 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1076 NdisZeroMemory(pTxWI, TXWI_SIZE);
1078 pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1079 pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1080 pTxWI->txop = pTxBlk->FrameGap;
1082 pTxWI->WirelessCliID = pTxBlk->Wcid;
1084 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1085 pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
1087 /* If CCK or OFDM, BW must be 20 */
1089 (pTransmit->field.MODE <=
1090 MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1091 pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
1093 /* John tune the performace with Intel Client in 20 MHz performance */
1094 BASize = pAd->CommonCfg.TxBASize;
1095 if ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry)) {
1096 u8 RABAOriIdx = 0; /*The RA's BA Originator table index. */
1099 pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
1100 BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1103 pTxWI->TxBF = pTransmit->field.TxBF;
1104 pTxWI->BAWinSize = BASize;
1105 pTxWI->ShortGI = pTransmit->field.ShortGI;
1106 pTxWI->STBC = pTransmit->field.STBC;
1108 pTxWI->MCS = pTransmit->field.MCS;
1109 pTxWI->PHYMODE = pTransmit->field.MODE;
1112 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC)
1113 && (pTransmit->field.MCS > 7)) {
1114 /* Dynamic MIMO Power Save Mode */
1116 } else if (pMacEntry->MmpsMode == MMPS_STATIC) {
1117 /* Static MIMO Power Save Mode */
1118 if (pTransmit->field.MODE >= MODE_HTMIX
1119 && pTransmit->field.MCS > 7) {
1125 if (pMacEntry->bIAmBadAtheros
1126 && (pMacEntry->WepStatus != Ndis802_11WEPDisabled)) {
1127 pTxWI->MpduDensity = 7;
1129 pTxWI->MpduDensity = pMacEntry->MpduDensity;
1133 /* for rate adapation */
1134 pTxWI->PacketId = pTxWI->MCS;
1137 void RTMPWriteTxWI_Cache(struct rt_rtmp_adapter *pAd,
1138 struct rt_txwi * pTxWI, struct rt_tx_blk *pTxBlk)
1140 PHTTRANSMIT_SETTING /*pTxHTPhyMode, */ pTransmit;
1141 struct rt_mac_table_entry *pMacEntry;
1146 pMacEntry = pTxBlk->pMacEntry;
1147 pTransmit = pTxBlk->pTransmit;
1149 /*if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */
1150 /*if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pMacEntry)) */
1151 /*if (TX_BLK_TEST_FLAG(pTxBlk, fTX_AutoRateSwitch)) */
1152 if (pMacEntry->bAutoTxRateSwitch) {
1153 pTxWI->txop = IFS_HTTXOP;
1155 /* If CCK or OFDM, BW must be 20 */
1157 (pTransmit->field.MODE <=
1158 MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1159 pTxWI->ShortGI = pTransmit->field.ShortGI;
1160 pTxWI->STBC = pTransmit->field.STBC;
1162 pTxWI->MCS = pTransmit->field.MCS;
1163 pTxWI->PHYMODE = pTransmit->field.MODE;
1165 /* set PID for TxRateSwitching */
1166 pTxWI->PacketId = pTransmit->field.MCS;
1169 pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE : FALSE);
1172 if (pAd->CommonCfg.bMIMOPSEnable) {
1173 /* MIMO Power Save Mode */
1174 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC)
1175 && (pTransmit->field.MCS > 7)) {
1176 /* Dynamic MIMO Power Save Mode */
1178 } else if (pMacEntry->MmpsMode == MMPS_STATIC) {
1179 /* Static MIMO Power Save Mode */
1180 if ((pTransmit->field.MODE >= MODE_HTMIX)
1181 && (pTransmit->field.MCS > 7)) {
1188 pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1192 /* should be called only when - */
1193 /* 1. MEADIA_CONNECTED */
1194 /* 2. AGGREGATION_IN_USED */
1195 /* 3. Fragmentation not in used */
1196 /* 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible */
1197 BOOLEAN TxFrameIsAggregatible(struct rt_rtmp_adapter *pAd,
1198 u8 *pPrevAddr1, u8 *p8023hdr)
1201 /* can't aggregate EAPOL (802.1x) frame */
1202 if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1205 /* can't aggregate multicast/broadcast frame */
1206 if (p8023hdr[0] & 0x01)
1209 if (INFRA_ON(pAd)) /* must be unicast to AP */
1211 else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) /* unicast to same STA */
1218 ========================================================================
1220 Routine Description:
1221 Check the MSDU Aggregation policy
1222 1.HT aggregation is A-MSDU
1223 2.legaacy rate aggregation is software aggregation by Ralink.
1231 ========================================================================
1233 BOOLEAN PeerIsAggreOn(struct rt_rtmp_adapter *pAd,
1234 unsigned long TxRate, struct rt_mac_table_entry *pMacEntry)
1236 unsigned long AFlags =
1237 (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
1239 if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags)) {
1240 if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) {
1243 #ifdef AGGREGATION_SUPPORT
1244 if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)))) { /* legacy Ralink Aggregation support */
1247 #endif /* AGGREGATION_SUPPORT // */
1255 ========================================================================
1257 Routine Description:
1258 Check and fine the packet waiting in SW queue with highest priority
1261 pAd Pointer to our adapter
1264 pQueue Pointer to Waiting Queue
1266 IRQL = DISPATCH_LEVEL
1270 ========================================================================
1272 struct rt_queue_header *RTMPCheckTxSwQueue(struct rt_rtmp_adapter *pAd, u8 *pQueIdx)
1275 unsigned long Number;
1276 /* 2004-11-15 to be removed. test aggregation only */
1277 /* if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2)) */
1280 Number = pAd->TxSwQueue[QID_AC_BK].Number
1281 + pAd->TxSwQueue[QID_AC_BE].Number
1282 + pAd->TxSwQueue[QID_AC_VI].Number
1283 + pAd->TxSwQueue[QID_AC_VO].Number;
1285 if (pAd->TxSwQueue[QID_AC_VO].Head != NULL) {
1286 *pQueIdx = QID_AC_VO;
1287 return (&pAd->TxSwQueue[QID_AC_VO]);
1288 } else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL) {
1289 *pQueIdx = QID_AC_VI;
1290 return (&pAd->TxSwQueue[QID_AC_VI]);
1291 } else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL) {
1292 *pQueIdx = QID_AC_BE;
1293 return (&pAd->TxSwQueue[QID_AC_BE]);
1294 } else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL) {
1295 *pQueIdx = QID_AC_BK;
1296 return (&pAd->TxSwQueue[QID_AC_BK]);
1298 /* No packet pending in Tx Sw queue */
1299 *pQueIdx = QID_AC_BK;
1305 ========================================================================
1307 Routine Description:
1308 Suspend MSDU transmission
1311 pAd Pointer to our adapter
1318 ========================================================================
1320 void RTMPSuspendMsduTransmission(struct rt_rtmp_adapter *pAd)
1322 DBGPRINT(RT_DEBUG_TRACE, ("SCANNING, suspend MSDU transmission ...\n"));
1325 /* Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and */
1326 /* use Lowbound as R66 value on ScanNextChannel(...) */
1328 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66,
1329 &pAd->BbpTuning.R66CurrentValue);
1331 /* set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning) */
1332 /*RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd))); */
1333 RTMPSetAGCInitValue(pAd, BW_20);
1335 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1336 /*RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000); // abort all TX rings */
1340 ========================================================================
1342 Routine Description:
1343 Resume MSDU transmission
1346 pAd Pointer to our adapter
1351 IRQL = DISPATCH_LEVEL
1355 ========================================================================
1357 void RTMPResumeMsduTransmission(struct rt_rtmp_adapter *pAd)
1361 DBGPRINT(RT_DEBUG_TRACE, ("SCAN done, resume MSDU transmission ...\n"));
1363 /* After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value */
1364 /* R66 should not be 0 */
1365 if (pAd->BbpTuning.R66CurrentValue == 0) {
1366 pAd->BbpTuning.R66CurrentValue = 0x38;
1367 DBGPRINT_ERR(("RTMPResumeMsduTransmission, R66CurrentValue=0...\n"));
1370 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66,
1371 pAd->BbpTuning.R66CurrentValue);
1373 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1374 /* sample, for IRQ LOCK to SEM LOCK */
1375 /* IrqState = pAd->irq_disabled; */
1377 /* RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS); */
1379 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1382 u32 deaggregate_AMSDU_announce(struct rt_rtmp_adapter *pAd,
1384 u8 *pData, unsigned long DataSize)
1388 struct rt_header_802_3 * pAMSDUsubheader;
1392 u8 *pPayload, *pDA, *pSA, *pRemovedLLCSNAP;
1397 while (DataSize > LENGTH_802_3) {
1401 /*hex_dump("subheader", pData, 64); */
1402 pAMSDUsubheader = (struct rt_header_802_3 *) pData;
1403 /*pData += LENGTH_802_3; */
1405 pAMSDUsubheader->Octet[1] +
1406 (pAMSDUsubheader->Octet[0] << 8);
1407 SubFrameSize = PayloadSize + LENGTH_802_3;
1409 if ((DataSize < SubFrameSize) || (PayloadSize > 1518)) {
1412 /*DBGPRINT(RT_DEBUG_TRACE,("%d subframe: Size = %d\n", nMSDU, PayloadSize)); */
1414 pPayload = pData + LENGTH_802_3;
1416 pSA = pData + MAC_ADDR_LEN;
1418 /* convert to 802.3 header */
1419 CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize,
1422 if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E)) {
1423 /* avoid local heap overflow, use dyanamic allocation */
1424 struct rt_mlme_queue_elem *Elem =
1425 (struct rt_mlme_queue_elem *)kmalloc(sizeof(struct rt_mlme_queue_elem),
1429 (LENGTH_802_11 + LENGTH_802_1_H),
1430 pPayload, PayloadSize);
1432 LENGTH_802_11 + LENGTH_802_1_H +
1434 /*WpaEAPOLKeyAction(pAd, Elem); */
1435 REPORT_MGMT_FRAME_TO_MLME(pAd, BSSID_WCID,
1437 Elem->MsgLen, 0, 0, 0,
1444 if (pRemovedLLCSNAP) {
1445 pPayload -= LENGTH_802_3;
1446 PayloadSize += LENGTH_802_3;
1447 NdisMoveMemory(pPayload, &Header802_3[0],
1452 pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
1454 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket,
1459 /* A-MSDU has padding to multiple of 4 including subframe header. */
1460 /* align SubFrameSize up to multiple of 4 */
1461 SubFrameSize = (SubFrameSize + 3) & (~0x3);
1463 if (SubFrameSize > 1528 || SubFrameSize < 32) {
1467 if (DataSize > SubFrameSize) {
1468 pData += SubFrameSize;
1469 DataSize -= SubFrameSize;
1476 /* finally release original rx packet */
1477 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1482 u32 BA_Reorder_AMSDU_Annnounce(struct rt_rtmp_adapter *pAd, void *pPacket)
1488 pData = (u8 *)GET_OS_PKT_DATAPTR(pPacket);
1489 DataSize = (u16)GET_OS_PKT_LEN(pPacket);
1491 nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
1497 ==========================================================================
1499 Look up the MAC address in the MAC table. Return NULL if not found.
1501 pEntry - pointer to the MAC entry; NULL is not found
1502 ==========================================================================
1504 struct rt_mac_table_entry *MacTableLookup(struct rt_rtmp_adapter *pAd, u8 *pAddr)
1506 unsigned long HashIdx;
1507 struct rt_mac_table_entry *pEntry = NULL;
1509 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1510 pEntry = pAd->MacTab.Hash[HashIdx];
1513 && (pEntry->ValidAsCLI || pEntry->ValidAsWDS
1514 || pEntry->ValidAsApCli || pEntry->ValidAsMesh)) {
1515 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) {
1518 pEntry = pEntry->pNext;
1524 struct rt_mac_table_entry *MacTableInsertEntry(struct rt_rtmp_adapter *pAd,
1526 u8 apidx, IN BOOLEAN CleanAll)
1530 struct rt_mac_table_entry *pEntry = NULL, *pCurrEntry;
1532 /* unsigned long addr; */
1534 /* if FULL, return */
1535 if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
1540 if (pAd->StaCfg.BssType == BSS_INFRA)
1543 /* allocate one MAC entry */
1544 NdisAcquireSpinLock(&pAd->MacTabLock);
1545 for (i = FirstWcid; i < MAX_LEN_OF_MAC_TABLE; i++) /* skip entry#0 so that "entry index == AID" for fast lookup */
1547 /* pick up the first available vacancy */
1548 if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
1549 (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
1550 (pAd->MacTab.Content[i].ValidAsApCli == FALSE) &&
1551 (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
1553 pEntry = &pAd->MacTab.Content[i];
1554 if (CleanAll == TRUE) {
1555 pEntry->MaxSupportedRate = RATE_11;
1556 pEntry->CurrTxRate = RATE_11;
1557 NdisZeroMemory(pEntry, sizeof(struct rt_mac_table_entry));
1558 pEntry->PairwiseKey.KeyLen = 0;
1559 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1563 pEntry->ValidAsCLI = TRUE;
1564 pEntry->ValidAsWDS = FALSE;
1565 pEntry->ValidAsApCli = FALSE;
1566 pEntry->ValidAsMesh = FALSE;
1567 pEntry->ValidAsDls = FALSE;
1571 pEntry->bIAmBadAtheros = FALSE;
1573 pEntry->CMTimerRunning = FALSE;
1574 pEntry->EnqueueEapolStartTimerRunning =
1575 EAPOL_START_DISABLE;
1576 pEntry->RSNIE_Len = 0;
1577 NdisZeroMemory(pEntry->R_Counter,
1578 sizeof(pEntry->R_Counter));
1579 pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
1581 if (pEntry->ValidAsMesh)
1583 (apidx - MIN_NET_DEVICE_FOR_MESH);
1584 else if (pEntry->ValidAsApCli)
1586 (apidx - MIN_NET_DEVICE_FOR_APCLI);
1587 else if (pEntry->ValidAsWDS)
1589 (apidx - MIN_NET_DEVICE_FOR_WDS);
1591 pEntry->apidx = apidx;
1595 pEntry->AuthMode = pAd->StaCfg.AuthMode;
1597 pAd->StaCfg.WepStatus;
1598 pEntry->PrivacyFilter =
1599 Ndis802_11PrivFilterAcceptAll;
1601 AsicRemovePairwiseKeyEntry(pAd,
1605 #endif /* RTMP_MAC_PCI // */
1609 pEntry->GTKState = REKEY_NEGOTIATING;
1610 pEntry->PairwiseKey.KeyLen = 0;
1611 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1612 pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
1614 pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
1615 COPY_MAC_ADDR(pEntry->Addr, pAddr);
1616 pEntry->Sst = SST_NOT_AUTH;
1617 pEntry->AuthState = AS_NOT_AUTH;
1618 pEntry->Aid = (u16)i; /*0; */
1619 pEntry->CapabilityInfo = 0;
1620 pEntry->PsMode = PWR_ACTIVE;
1621 pEntry->PsQIdleCount = 0;
1622 pEntry->NoDataIdleCount = 0;
1623 pEntry->AssocDeadLine = MAC_TABLE_ASSOC_TIMEOUT;
1624 pEntry->ContinueTxFailCnt = 0;
1625 InitializeQueueHeader(&pEntry->PsQueue);
1628 /* Add this entry into ASIC RX WCID search table */
1629 RTMP_STA_ENTRY_ADD(pAd, pEntry);
1631 DBGPRINT(RT_DEBUG_TRACE,
1632 ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",
1633 i, pAd->MacTab.Size));
1638 /* add this MAC entry into HASH table */
1640 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1641 if (pAd->MacTab.Hash[HashIdx] == NULL) {
1642 pAd->MacTab.Hash[HashIdx] = pEntry;
1644 pCurrEntry = pAd->MacTab.Hash[HashIdx];
1645 while (pCurrEntry->pNext != NULL)
1646 pCurrEntry = pCurrEntry->pNext;
1647 pCurrEntry->pNext = pEntry;
1651 NdisReleaseSpinLock(&pAd->MacTabLock);
1656 ==========================================================================
1658 Delete a specified client from MAC table
1659 ==========================================================================
1661 BOOLEAN MacTableDeleteEntry(struct rt_rtmp_adapter *pAd,
1662 u16 wcid, u8 *pAddr)
1665 struct rt_mac_table_entry *pEntry, *pPrevEntry, *pProbeEntry;
1667 /*u16 offset; // unused variable */
1668 /*u8 j; // unused variable */
1670 if (wcid >= MAX_LEN_OF_MAC_TABLE)
1673 NdisAcquireSpinLock(&pAd->MacTabLock);
1675 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1676 /*pEntry = pAd->MacTab.Hash[HashIdx]; */
1677 pEntry = &pAd->MacTab.Content[wcid];
1680 && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS
1681 || pEntry->ValidAsMesh)) {
1682 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) {
1684 /* Delete this entry from ASIC on-chip WCID Table */
1685 RTMP_STA_ENTRY_MAC_RESET(pAd, wcid);
1687 /* free resources of BA */
1688 BASessionTearDownALL(pAd, pEntry->Aid);
1691 pProbeEntry = pAd->MacTab.Hash[HashIdx];
1692 ASSERT(pProbeEntry);
1694 /* update Hash list */
1696 if (pProbeEntry == pEntry) {
1697 if (pPrevEntry == NULL) {
1698 pAd->MacTab.Hash[HashIdx] =
1707 pPrevEntry = pProbeEntry;
1708 pProbeEntry = pProbeEntry->pNext;
1709 } while (pProbeEntry);
1712 ASSERT(pProbeEntry != NULL);
1714 RTMP_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
1716 if (pEntry->EnqueueEapolStartTimerRunning !=
1717 EAPOL_START_DISABLE) {
1718 RTMPCancelTimer(&pEntry->
1719 EnqueueStartForPSKTimer,
1721 pEntry->EnqueueEapolStartTimerRunning =
1722 EAPOL_START_DISABLE;
1725 NdisZeroMemory(pEntry, sizeof(struct rt_mac_table_entry));
1727 DBGPRINT(RT_DEBUG_TRACE,
1728 ("MacTableDeleteEntry1 - Total= %d\n",
1731 DBGPRINT(RT_DEBUG_OFF,
1732 ("\n%s: Impossible Wcid = %d !!!!!\n",
1737 NdisReleaseSpinLock(&pAd->MacTabLock);
1739 /*Reset operating mode when no Sta. */
1740 if (pAd->MacTab.Size == 0) {
1741 pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
1742 RTMP_UPDATE_PROTECT(pAd); /* edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet */
1749 ==========================================================================
1751 This routine reset the entire MAC table. All packets pending in
1752 the power-saving queues are freed here.
1753 ==========================================================================
1755 void MacTableReset(struct rt_rtmp_adapter *pAd)
1759 DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
1760 /*NdisAcquireSpinLock(&pAd->MacTabLock); */
1762 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
1764 RTMP_STA_ENTRY_MAC_RESET(pAd, i);
1765 #endif /* RTMP_MAC_PCI // */
1766 if (pAd->MacTab.Content[i].ValidAsCLI == TRUE) {
1768 /* free resources of BA */
1769 BASessionTearDownALL(pAd, i);
1771 pAd->MacTab.Content[i].ValidAsCLI = FALSE;
1774 NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6);
1775 RTMP_STA_ENTRY_MAC_RESET(pAd, i);
1776 #endif /* RTMP_MAC_USB // */
1778 /*AsicDelWcidTab(pAd, i); */
1786 ==========================================================================
1789 IRQL = DISPATCH_LEVEL
1791 ==========================================================================
1793 void AssocParmFill(struct rt_rtmp_adapter *pAd,
1794 struct rt_mlme_assoc_req *AssocReq,
1797 unsigned long Timeout, u16 ListenIntv)
1799 COPY_MAC_ADDR(AssocReq->Addr, pAddr);
1800 /* Add mask to support 802.11b mode only */
1801 AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; /* not cf-pollable, not cf-poll-request */
1802 AssocReq->Timeout = Timeout;
1803 AssocReq->ListenIntv = ListenIntv;
1807 ==========================================================================
1810 IRQL = DISPATCH_LEVEL
1812 ==========================================================================
1814 void DisassocParmFill(struct rt_rtmp_adapter *pAd,
1815 struct rt_mlme_disassoc_req *DisassocReq,
1816 u8 *pAddr, u16 Reason)
1818 COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
1819 DisassocReq->Reason = Reason;
1823 ========================================================================
1825 Routine Description:
1826 Check the out going frame, if this is an DHCP or ARP datagram
1827 will be duplicate another frame at low data rate transmit.
1830 pAd Pointer to our adapter
1831 pPacket Pointer to outgoing Ndis frame
1834 TRUE To be duplicate at Low data rate transmit. (1mb)
1837 IRQL = DISPATCH_LEVEL
1841 MAC header + IP Header + UDP Header
1845 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
1847 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
1850 port 0x43 means Bootstrap Protocol, server.
1851 Port 0x44 means Bootstrap Protocol, client.
1853 ========================================================================
1856 BOOLEAN RTMPCheckDHCPFrame(struct rt_rtmp_adapter *pAd, void *pPacket)
1858 struct rt_packet_info PacketInfo;
1859 unsigned long NumberOfBytesRead = 0;
1860 unsigned long CurrentOffset = 0;
1861 void *pVirtualAddress = NULL;
1862 u32 NdisBufferLength;
1865 u8 ByteOffset36 = 0;
1866 u8 ByteOffset38 = 0;
1867 BOOLEAN ReadFirstParm = TRUE;
1869 RTMP_QueryPacketInfo(pPacket, &PacketInfo, (u8 **) & pVirtualAddress,
1872 NumberOfBytesRead += NdisBufferLength;
1873 pSrc = (u8 *)pVirtualAddress;
1874 Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
1877 /* Check DHCP & BOOTP protocol */
1879 while (NumberOfBytesRead <= PacketInfo.TotalPacketLength) {
1880 if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE)) {
1882 35 - (NumberOfBytesRead - NdisBufferLength);
1883 ByteOffset36 = *(pSrc + CurrentOffset);
1884 ReadFirstParm = FALSE;
1887 if (NumberOfBytesRead >= 37) {
1889 37 - (NumberOfBytesRead - NdisBufferLength);
1890 ByteOffset38 = *(pSrc + CurrentOffset);
1897 /* Check for DHCP & BOOTP protocol */
1898 if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43)) {
1900 /* 2054 (hex 0806) for ARP datagrams */
1901 /* if this packet is not ARP datagrams, then do nothing */
1902 /* ARP datagrams will also be duplicate at 1mb broadcast frames */
1904 if (Protocol != 0x0806)
1911 BOOLEAN RTMPCheckEtherType(struct rt_rtmp_adapter *pAd, void *pPacket)
1917 u16 srcPort, dstPort;
1918 BOOLEAN status = TRUE;
1920 pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
1921 pktLen = GET_OS_PKT_LEN(pPacket);
1925 RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
1927 /* get Ethernet protocol field */
1928 TypeLen = (pSrcBuf[12] << 8) | pSrcBuf[13];
1930 pSrcBuf += LENGTH_802_3; /* Skip the Ethernet Header. */
1932 if (TypeLen <= 1500) { /* 802.3, 802.3 LLC */
1934 DestMAC(6) + SrcMAC(6) + Lenght(2) +
1935 DSAP(1) + SSAP(1) + Control(1) +
1936 if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
1937 => + SNAP (5, OriginationID(3) + etherType(2))
1939 if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA
1940 && pSrcBuf[2] == 0x03) {
1941 Sniff2BytesFromNdisBuffer((char *)pSrcBuf, 6,
1943 RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
1944 TypeLen = (u16)((Byte0 << 8) + Byte1);
1945 pSrcBuf += 8; /* Skip this LLC/SNAP header */
1947 /*It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it. */
1950 /* If it's a VLAN packet, get the real Type/Length field. */
1951 if (TypeLen == 0x8100) {
1952 /* 0x8100 means VLAN packets */
1954 /* Dest. MAC Address (6-bytes) +
1955 Source MAC Address (6-bytes) +
1956 Length/Type = 802.1Q Tag Type (2-byte) +
1957 Tag Control Information (2-bytes) +
1958 Length / Type (2-bytes) +
1959 data payload (0-n bytes) +
1961 Frame Check Sequence (4-bytes) */
1963 RTMP_SET_PACKET_VLAN(pPacket, 1);
1964 Sniff2BytesFromNdisBuffer((char *)pSrcBuf, 2, &Byte0,
1966 TypeLen = (u16)((Byte0 << 8) + Byte1);
1968 pSrcBuf += 4; /* Skip the VLAN Header. */
1974 ASSERT((pktLen > 34));
1975 if (*(pSrcBuf + 9) == 0x11) { /* udp packet */
1976 ASSERT((pktLen > 34)); /* 14 for ethernet header, 20 for IP header */
1978 pSrcBuf += 20; /* Skip the IP header */
1980 OS_NTOHS(get_unaligned
1981 ((u16 *)(pSrcBuf)));
1983 OS_NTOHS(get_unaligned
1984 ((u16 *)(pSrcBuf + 2)));
1986 if ((srcPort == 0x44 && dstPort == 0x43) || (srcPort == 0x43 && dstPort == 0x44)) { /*It's a BOOTP/DHCP packet */
1987 RTMP_SET_PACKET_DHCP(pPacket, 1);
1995 RTMP_SET_PACKET_DHCP(pPacket, 1);
2001 RTMP_SET_PACKET_EAPOL(pPacket, 1);
2013 void Update_Rssi_Sample(struct rt_rtmp_adapter *pAd,
2014 struct rt_rssi_sample *pRssi, struct rt_rxwi * pRxWI)
2016 char rssi0 = pRxWI->RSSI0;
2017 char rssi1 = pRxWI->RSSI1;
2018 char rssi2 = pRxWI->RSSI2;
2021 pRssi->LastRssi0 = ConvertToRssi(pAd, (char)rssi0, RSSI_0);
2023 (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
2024 pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
2028 pRssi->LastRssi1 = ConvertToRssi(pAd, (char)rssi1, RSSI_1);
2030 (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
2031 pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
2035 pRssi->LastRssi2 = ConvertToRssi(pAd, (char)rssi2, RSSI_2);
2037 (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
2038 pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
2042 /* Normal legacy Rx packet indication */
2043 void Indicate_Legacy_Packet(struct rt_rtmp_adapter *pAd,
2044 struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
2046 void *pRxPacket = pRxBlk->pRxPacket;
2047 u8 Header802_3[LENGTH_802_3];
2049 /* 1. get 802.3 Header */
2051 /* a. pointer pRxBlk->pData to payload */
2052 /* b. modify pRxBlk->DataSize */
2053 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2055 if (pRxBlk->DataSize > MAX_RX_PKT_LEN) {
2057 /* release packet */
2058 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2062 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
2065 if (pAd->CommonCfg.bDisableReordering == 0) {
2066 struct rt_ba_rec_entry *pBAEntry;
2067 unsigned long Now32;
2068 u8 Wcid = pRxBlk->pRxWI->WirelessCliID;
2069 u8 TID = pRxBlk->pRxWI->TID;
2072 #define REORDERING_PACKET_TIMEOUT ((100 * OS_HZ)/1000) /* system ticks -- 100 ms */
2074 if (Wcid < MAX_LEN_OF_MAC_TABLE) {
2075 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
2077 pBAEntry = &pAd->BATable.BARecEntry[Idx];
2078 /* update last rx time */
2079 NdisGetSystemUpTime(&Now32);
2080 if ((pBAEntry->list.qlen > 0) &&
2081 RTMP_TIME_AFTER((unsigned long)Now32,
2082 (unsigned long)(pBAEntry->
2085 (REORDERING_PACKET_TIMEOUT)))
2087 DBGPRINT(RT_DEBUG_OFF,
2088 ("Indicate_Legacy_Packet():flush reordering_timeout_mpdus! RxWI->Flags=%d, pRxWI.TID=%d, RxD->AMPDU=%d!\n",
2091 pRxBlk->RxD.AMPDU));
2092 hex_dump("Dump the legacy Packet:",
2093 GET_OS_PKT_DATAPTR(pRxBlk->
2096 ba_flush_reordering_timeout_mpdus(pAd,
2103 #endif /* RTMP_MAC_USB // */
2105 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2108 /* pass this 802.3 packet to upper layer or forward this packet to WM directly */
2110 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
2113 /* Normal, AMPDU or AMSDU */
2114 void CmmRxnonRalinkFrameIndicate(struct rt_rtmp_adapter *pAd,
2115 struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
2117 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU)
2118 && (pAd->CommonCfg.bDisableReordering == 0)) {
2119 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2121 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) {
2123 Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2125 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
2130 void CmmRxRalinkFrameIndicate(struct rt_rtmp_adapter *pAd,
2131 struct rt_mac_table_entry *pEntry,
2132 struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
2134 u8 Header802_3[LENGTH_802_3];
2136 u16 Payload1Size, Payload2Size;
2138 void *pPacket2 = NULL;
2140 Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData + 1) << 8);
2142 if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize)) {
2143 /* skip two byte MSDU2 len */
2145 pRxBlk->DataSize -= 2;
2147 /* release packet */
2148 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
2149 NDIS_STATUS_FAILURE);
2153 /* get 802.3 Header and remove LLC */
2154 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2156 ASSERT(pRxBlk->pRxPacket);
2158 /* Ralink Aggregation frame */
2159 pAd->RalinkCounters.OneSecRxAggregationCount++;
2160 Payload1Size = pRxBlk->DataSize - Msdu2Size;
2161 Payload2Size = Msdu2Size - LENGTH_802_3;
2163 pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
2166 duplicate_pkt(pAd, (pData2 - LENGTH_802_3), LENGTH_802_3, pData2,
2167 Payload2Size, FromWhichBSSID);
2170 /* release packet */
2171 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
2172 NDIS_STATUS_FAILURE);
2175 /* update payload size of 1st packet */
2176 pRxBlk->DataSize = Payload1Size;
2177 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2179 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket,
2183 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
2187 #define RESET_FRAGFRAME(_fragFrame) \
2189 _fragFrame.RxSize = 0; \
2190 _fragFrame.Sequence = 0; \
2191 _fragFrame.LastFrag = 0; \
2192 _fragFrame.Flags = 0; \
2195 void *RTMPDeFragmentDataFrame(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk)
2197 struct rt_header_802_11 * pHeader = pRxBlk->pHeader;
2198 void *pRxPacket = pRxBlk->pRxPacket;
2199 u8 *pData = pRxBlk->pData;
2200 u16 DataSize = pRxBlk->DataSize;
2201 void *pRetPacket = NULL;
2202 u8 *pFragBuffer = NULL;
2203 BOOLEAN bReassDone = FALSE;
2208 HeaderRoom = pData - (u8 *) pHeader;
2210 /* Re-assemble the fragmented packets */
2211 if (pHeader->Frag == 0) /* Frag. Number is 0 : First frag or only one pkt */
2213 /* the first pkt of fragment, record it. */
2214 if (pHeader->FC.MoreFrag) {
2215 ASSERT(pAd->FragFrame.pFragPacket);
2217 GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2218 pAd->FragFrame.RxSize = DataSize + HeaderRoom;
2219 NdisMoveMemory(pFragBuffer, pHeader,
2220 pAd->FragFrame.RxSize);
2221 pAd->FragFrame.Sequence = pHeader->Sequence;
2222 pAd->FragFrame.LastFrag = pHeader->Frag; /* Should be 0 */
2223 ASSERT(pAd->FragFrame.LastFrag == 0);
2224 goto done; /* end of processing this frame */
2226 } else /*Middle & End of fragment */
2228 if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
2229 (pHeader->Frag != (pAd->FragFrame.LastFrag + 1))) {
2230 /* Fragment is not the same sequence or out of fragment number order */
2231 /* Reset Fragment control blk */
2232 RESET_FRAGFRAME(pAd->FragFrame);
2233 DBGPRINT(RT_DEBUG_ERROR,
2234 ("Fragment is not the same sequence or out of fragment number order.\n"));
2235 goto done; /* give up this frame */
2236 } else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE) {
2237 /* Fragment frame is too large, it exeeds the maximum frame size. */
2238 /* Reset Fragment control blk */
2239 RESET_FRAGFRAME(pAd->FragFrame);
2240 DBGPRINT(RT_DEBUG_ERROR,
2241 ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
2242 goto done; /* give up this frame */
2245 /* Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment. */
2246 /* In this case, we will dropt it. */
2248 if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H))) {
2249 DBGPRINT(RT_DEBUG_ERROR,
2250 ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n",
2251 pHeader->Sequence, pHeader->Frag));
2252 goto done; /* give up this frame */
2255 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2257 /* concatenate this fragment into the re-assembly buffer */
2258 NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData,
2260 pAd->FragFrame.RxSize += DataSize;
2261 pAd->FragFrame.LastFrag = pHeader->Frag; /* Update fragment number */
2264 if (pHeader->FC.MoreFrag == FALSE) {
2270 /* always release rx fragmented packet */
2271 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2273 /* return defragmented packet if packet is reassembled completely */
2274 /* otherwise return NULL */
2276 void *pNewFragPacket;
2278 /* allocate a new packet buffer for fragment */
2280 RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
2281 if (pNewFragPacket) {
2283 pRetPacket = pAd->FragFrame.pFragPacket;
2284 pAd->FragFrame.pFragPacket = pNewFragPacket;
2286 (struct rt_header_802_11 *) GET_OS_PKT_DATAPTR(pRetPacket);
2287 pRxBlk->pData = (u8 *) pRxBlk->pHeader + HeaderRoom;
2288 pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
2289 pRxBlk->pRxPacket = pRetPacket;
2291 RESET_FRAGFRAME(pAd->FragFrame);
2298 void Indicate_AMSDU_Packet(struct rt_rtmp_adapter *pAd,
2299 struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
2303 update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
2304 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
2306 deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData,
2310 void Indicate_EAPOL_Packet(struct rt_rtmp_adapter *pAd,
2311 struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
2313 struct rt_mac_table_entry *pEntry = NULL;
2316 pEntry = &pAd->MacTab.Content[BSSID_WCID];
2317 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
2321 if (pEntry == NULL) {
2322 DBGPRINT(RT_DEBUG_WARN,
2323 ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
2324 /* release packet */
2325 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
2326 NDIS_STATUS_FAILURE);
2331 #define BCN_TBTT_OFFSET 64 /*defer 64 us */
2332 void ReSyncBeaconTime(struct rt_rtmp_adapter *pAd)
2337 Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
2339 pAd->TbttTickCount++;
2342 /* The updated BeaconInterval Value will affect Beacon Interval after two TBTT */
2343 /* beacasue the original BeaconInterval had been loaded into next TBTT_TIMER */
2345 if (Offset == (BCN_TBTT_OFFSET - 2)) {
2346 BCN_TIME_CFG_STRUC csr;
2347 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2348 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1; /* ASIC register in units of 1/16 TU = 64us */
2349 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2351 if (Offset == (BCN_TBTT_OFFSET - 1)) {
2352 BCN_TIME_CFG_STRUC csr;
2354 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2355 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; /* ASIC register in units of 1/16 TU */
2356 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);