Staging: rt28x0: fix comments in common/*.c files
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / rt2860 / common / cmm_data.c
blob81766db533ec65e39987c3404a55ace273d20064
1 /*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
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. *
14 * *
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. *
19 * *
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. *
24 * *
25 *************************************************************************
28 #include "../rt_config.h"
30 UCHAR SNAP_802_1H[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
31 UCHAR SNAP_BRIDGE_TUNNEL[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
33 /* Add Cisco Aironet SNAP heade for CCX2 support */
34 UCHAR SNAP_AIRONET[] = { 0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00 };
35 UCHAR CKIP_LLC_SNAP[] = { 0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02 };
36 UCHAR EAPOL_LLC_SNAP[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e };
37 UCHAR EAPOL[] = { 0x88, 0x8e };
38 UCHAR TPID[] = { 0x81, 0x00 }; /* VLAN related */
40 UCHAR IPX[] = { 0x81, 0x37 };
41 UCHAR APPLE_TALK[] = { 0x80, 0xf3 };
43 UCHAR 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 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] = {
57 0, 0, 0, 0,
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 UCHAR 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 */
68 char *MCSToMbps[] =
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" };
74 UCHAR default_cwmin[] =
75 { CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS - 1, CW_MIN_IN_BITS - 2 };
76 /*UCHAR default_cwmax[]={CW_MAX_IN_BITS, CW_MAX_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1}; */
77 UCHAR default_sta_aifsn[] = { 3, 7, 2, 2 };
79 UCHAR 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 ========================================================================
86 Routine Description:
87 API for MLME to transmit management frame to AP (BSS Mode)
88 or station (IBSS Mode)
90 Arguments:
91 pAd Pointer to our adapter
92 pData Pointer to the outgoing 802.11 frame
93 Length Size of outgoing management frame
95 Return Value:
96 NDIS_STATUS_FAILURE
97 NDIS_STATUS_PENDING
98 NDIS_STATUS_SUCCESS
100 IRQL = PASSIVE_LEVEL
101 IRQL = DISPATCH_LEVEL
103 Note:
105 ========================================================================
107 NDIS_STATUS MiniportMMRequest(IN PRTMP_ADAPTER pAd,
108 IN UCHAR QueIdx, IN PUCHAR pData, IN UINT Length)
110 PNDIS_PACKET pPacket;
111 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
112 ULONG FreeNum;
113 UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; /*RTMP_HW_HDR_LEN]; */
114 #ifdef RTMP_MAC_PCI
115 unsigned long IrqFlags = 0;
116 UCHAR IrqState;
117 #endif /* RTMP_MAC_PCI // */
118 BOOLEAN bUseDataQ = FALSE;
119 int retryCnt = 0;
121 ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
123 if ((QueIdx & MGMT_USE_QUEUE_FLAG) == MGMT_USE_QUEUE_FLAG) {
124 bUseDataQ = TRUE;
125 QueIdx &= (~MGMT_USE_QUEUE_FLAG);
127 #ifdef RTMP_MAC_PCI
128 /* 2860C use Tx Ring */
129 IrqState = pAd->irq_disabled;
130 if (pAd->MACVersion == 0x28600100) {
131 QueIdx = (bUseDataQ == TRUE ? QueIdx : 3);
132 bUseDataQ = TRUE;
134 if (bUseDataQ && (!IrqState))
135 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
136 #endif /* RTMP_MAC_PCI // */
138 do {
139 /* Reset is in progress, stop immediately */
140 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
141 RTMP_TEST_FLAG(pAd,
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;
146 break;
148 /* Check Free priority queue */
149 /* Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing. */
150 #ifdef RTMP_MAC_PCI
151 if (bUseDataQ) {
152 retryCnt = MAX_DATAMM_RETRY;
153 /* free Tx(QueIdx) resources */
154 RTMPFreeTXDUponTxDmaDone(pAd, QueIdx);
155 FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
156 } else
157 #endif /* RTMP_MAC_PCI // */
159 FreeNum = GET_MGMTRING_FREENO(pAd);
162 if ((FreeNum > 0)) {
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));
165 Status =
166 RTMPAllocateNdisPacket(pAd, &pPacket,
167 (PUCHAR) & rtmpHwHdr,
168 (TXINFO_SIZE + TXWI_SIZE),
169 pData, Length);
170 if (Status != NDIS_STATUS_SUCCESS) {
171 DBGPRINT(RT_DEBUG_WARN,
172 ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
173 break;
175 /*pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; */
176 /*pAd->CommonCfg.MlmeRate = RATE_2; */
178 #ifdef RTMP_MAC_PCI
179 if (bUseDataQ) {
180 Status =
181 MlmeDataHardTransmit(pAd, QueIdx, pPacket);
182 retryCnt--;
183 } else
184 #endif /* RTMP_MAC_PCI // */
185 Status = MlmeHardTransmit(pAd, QueIdx, pPacket);
186 if (Status == NDIS_STATUS_SUCCESS)
187 retryCnt = 0;
188 else
189 RTMPFreeNdisPacket(pAd, pPacket);
190 } else {
191 pAd->RalinkCounters.MgmtRingFullCount++;
192 #ifdef RTMP_MAC_PCI
193 if (bUseDataQ) {
194 retryCnt--;
195 DBGPRINT(RT_DEBUG_TRACE,
196 ("retryCnt %d\n", retryCnt));
197 if (retryCnt == 0) {
198 DBGPRINT(RT_DEBUG_ERROR,
199 ("Qidx(%d), not enough space in DataRing, MgmtRingFullCount=%ld!\n",
200 QueIdx,
201 pAd->RalinkCounters.
202 MgmtRingFullCount));
205 #endif /* RTMP_MAC_PCI // */
206 DBGPRINT(RT_DEBUG_ERROR,
207 ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n",
208 QueIdx,
209 pAd->RalinkCounters.MgmtRingFullCount));
211 } while (retryCnt > 0);
213 #ifdef RTMP_MAC_PCI
214 if (bUseDataQ && (!IrqState))
215 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
216 #endif /* RTMP_MAC_PCI // */
218 return Status;
222 ========================================================================
224 Routine Description:
225 Copy frame from waiting queue into relative ring buffer and set
226 appropriate ASIC register to kick hardware transmit function
228 Arguments:
229 pAd Pointer to our adapter
230 pBuffer Pointer to memory of outgoing frame
231 Length Size of outgoing management frame
233 Return Value:
234 NDIS_STATUS_FAILURE
235 NDIS_STATUS_PENDING
236 NDIS_STATUS_SUCCESS
238 IRQL = PASSIVE_LEVEL
239 IRQL = DISPATCH_LEVEL
241 Note:
243 ========================================================================
245 NDIS_STATUS MlmeHardTransmit(IN PRTMP_ADAPTER pAd,
246 IN UCHAR QueIdx, IN PNDIS_PACKET pPacket)
248 PACKET_INFO PacketInfo;
249 PUCHAR pSrcBufVA;
250 UINT SrcBufLen;
251 PHEADER_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 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE);
264 #ifdef RTMP_MAC_PCI
265 if (pAd->MACVersion == 0x28600100)
266 return MlmeHardTransmitTxRing(pAd, QueIdx, pPacket);
267 else
268 #endif /* RTMP_MAC_PCI // */
269 return MlmeHardTransmitMgmtRing(pAd, QueIdx, pPacket);
273 NDIS_STATUS MlmeHardTransmitMgmtRing(IN PRTMP_ADAPTER pAd,
274 IN UCHAR QueIdx, IN PNDIS_PACKET pPacket)
276 PACKET_INFO PacketInfo;
277 PUCHAR pSrcBufVA;
278 UINT SrcBufLen;
279 PHEADER_802_11 pHeader_802_11;
280 BOOLEAN bAckRequired, bInsertTimestamp;
281 UCHAR MlmeRate;
282 PTXWI_STRUC pFirstTxWI;
283 MAC_TABLE_ENTRY *pMacEntry = NULL;
284 UCHAR PID;
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 = (PTXWI_STRUC) (pSrcBufVA + TXINFO_SIZE);
303 pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); /*TXWI_SIZE); */
305 if (pHeader_802_11->Addr1[0] & 0x01) {
306 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
307 } else {
308 MlmeRate = pAd->CommonCfg.MlmeRate;
311 /* Verify Mlme rate for a / g bands. */
312 if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) /* 11A band */
313 MlmeRate = RATE_6;
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;
326 else
327 pAd->CommonCfg.MlmeTransmit.field.MODE = 0;
331 /* */
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. */
335 /* */
336 pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE; /* (pAd->StaCfg.Psm == PWR_SAVE); */
338 /* */
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;
349 else
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;
373 } else {
374 bAckRequired = TRUE;
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 */
381 } else
382 if ((pHeader_802_11->FC.SubType ==
383 SUBTYPE_PROBE_REQ)
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)
392 pAd->Sequence = 0;
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"));
401 /* if (!IrqState) */
402 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
403 return (NDIS_STATUS_FAILURE);
406 /* */
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 */
410 /* */
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. */
418 PID = PID_MGMT;
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 (UCHAR) pAd->CommonCfg.MlmeTransmit.field.MCS,
425 IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
426 } else {
427 /* dont use low rate to send QoS Null data frame */
428 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
429 bInsertTimestamp, FALSE, bAckRequired, FALSE,
430 0, pMacEntry->Aid,
431 (SrcBufLen - TXINFO_SIZE - TXWI_SIZE),
432 pMacEntry->MaxHTPhyMode.field.MCS, 0,
433 (UCHAR) 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 */
441 /* if (!IrqState) */
442 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
443 return NDIS_STATUS_SUCCESS;
446 /********************************************************************************
448 New DeQueue Procedures.
450 ********************************************************************************/
452 #define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \
453 do{ \
454 if (bIntContext == FALSE) \
455 RTMP_IRQ_LOCK((lock), IrqFlags); \
456 }while(0)
458 #define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \
459 do{ \
460 if (bIntContext == FALSE) \
461 RTMP_IRQ_UNLOCK((lock), IrqFlags); \
462 }while(0)
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.
481 Fragment:
482 The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
484 Classified Packet Handle Rule=>
485 Multicast:
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;
494 11N Rate :
495 No piggyback, //pTxBlk->bPiggyBack = FALSE;
497 (1).AMSDU
498 pTxBlk->bWMM = TRUE;
499 (2).AMPDU
500 pTxBlk->bWMM = TRUE;
501 (3).Normal
503 B/G Rate :
504 (1).ARALINK
506 (2).Normal
507 ========================================================================
509 static UCHAR TxPktClassification(IN RTMP_ADAPTER * pAd, IN PNDIS_PACKET pPacket)
511 UCHAR TxFrameType = TX_UNKOWN_FRAME;
512 UCHAR Wcid;
513 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 */
528 bHTRate = TRUE;
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;
539 else
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;
544 } else {
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;
554 return TxFrameType;
557 BOOLEAN RTMP_FillTxBlkInfo(IN RTMP_ADAPTER * pAd, IN TX_BLK * pTxBlk)
559 PACKET_INFO PacketInfo;
560 PNDIS_PACKET pPacket;
561 PMAC_TABLE_ENTRY pMacEntry = NULL;
563 pPacket = pTxBlk->pPacket;
564 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader,
565 &pTxBlk->SrcBufLen);
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);
574 else
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;
583 pTxBlk->pTransmit =
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);
595 } else {
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);
604 else
605 TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired);
607 if ((pAd->OpMode == OPMODE_STA) &&
608 (ADHOC_ON(pAd)) &&
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. */
631 pTxBlk->pTransmit =
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,
644 fTX_bForceNonQoS);
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++;
662 return TRUE;
665 BOOLEAN CanDoAggregateTransmit(IN RTMP_ADAPTER * pAd,
666 IN NDIS_PACKET * pPacket, IN 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)
672 return FALSE;
674 if (RTMP_GET_PACKET_DHCP(pPacket) ||
675 RTMP_GET_PACKET_EAPOL(pPacket) || RTMP_GET_PACKET_WAI(pPacket))
676 return FALSE;
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 */
679 return FALSE;
682 if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) && (pTxBlk->TxPacketList.Number == 2)) { /* For RALINK-Aggregation, allow two frames in one batch. */
683 return FALSE;
686 if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) /* must be unicast to AP */
687 return TRUE;
688 else
689 return FALSE;
694 ========================================================================
696 Routine Description:
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.
702 Arguments:
703 pAd Pointer to our adapter
704 pQueue Pointer to Waiting Queue
706 Return Value:
707 None
709 IRQL = DISPATCH_LEVEL
711 Note:
713 ========================================================================
715 VOID RTMPDeQueuePacket(IN PRTMP_ADAPTER pAd, IN BOOLEAN bIntContext, IN UCHAR QIdx, /* BulkOutPipeId */
716 IN UCHAR Max_Tx_Packets)
718 PQUEUE_ENTRY pEntry = NULL;
719 PNDIS_PACKET pPacket;
720 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
721 UCHAR Count = 0;
722 PQUEUE_HEADER pQueue;
723 ULONG FreeNumber[NUM_OF_TX_RING];
724 UCHAR QueIdx, sQIdx, eQIdx;
725 unsigned long IrqFlags = 0;
726 BOOLEAN hasTxDesc = FALSE;
727 TX_BLK TxBlk;
728 TX_BLK *pTxBlk;
730 if (QIdx == NUM_OF_TX_RING) {
731 sQIdx = 0;
732 eQIdx = 3; /* 4 ACs, start from 0. */
733 } else {
734 sQIdx = eQIdx = QIdx;
737 for (QueIdx = sQIdx; QueIdx <= eQIdx; QueIdx++) {
738 Count = 0;
740 RTMP_START_DEQUEUE(pAd, QueIdx, IrqFlags);
742 while (1) {
743 if ((RTMP_TEST_FLAG
744 (pAd,
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);
751 return;
754 if (Count >= Max_Tx_Packets)
755 break;
757 DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
758 if (&pAd->TxSwQueue[QueIdx] == NULL) {
759 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext,
760 IrqFlags);
761 break;
763 #ifdef RTMP_MAC_PCI
764 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
766 if (FreeNumber[QueIdx] <= 5) {
767 /* free Tx(QueIdx) resources */
768 RTMPFreeTXDUponTxDmaDone(pAd, QueIdx);
769 FreeNumber[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,
778 IrqFlags);
779 break;
782 pTxBlk = &TxBlk;
783 NdisZeroMemory((PUCHAR) pTxBlk, sizeof(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. */
790 hasTxDesc =
791 RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk,
792 FreeNumber[QueIdx],
793 pPacket);
794 if (!hasTxDesc) {
795 pAd->PrivateInfo.TxRingFullCnt++;
797 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext,
798 IrqFlags);
800 break;
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
820 (pPacket));
821 DEQUEUE_UNLOCK(&pAd->irq_lock,
822 bIntContext, IrqFlags);
823 break;
826 do {
827 if ((pEntry = pQueue->Head) == NULL)
828 break;
830 /* For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation. */
831 pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
832 FreeNumber[QueIdx] =
833 GET_TXRING_FREENO(pAd, QueIdx);
834 hasTxDesc =
835 RTMP_HAS_ENOUGH_FREE_DESC(pAd,
836 pTxBlk,
837 FreeNumber
838 [QueIdx],
839 pPacket);
840 if ((hasTxDesc == FALSE)
842 (CanDoAggregateTransmit
843 (pAd, pPacket, pTxBlk) == FALSE))
844 break;
846 /*Remove the packet from the TxSwQueue and insert into pTxBlk */
847 pEntry = RemoveHeadQueue(pQueue);
848 ASSERT(pEntry);
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
856 (pPacket));
857 } while (1);
859 if (pTxBlk->TxPacketList.Number == 1)
860 pTxBlk->TxFrameType = TX_LEGACY_FRAME;
862 #ifdef RTMP_MAC_USB
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);
870 #ifdef RTMP_MAC_PCI
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);
881 #ifdef RTMP_MAC_USB
882 if (!hasTxDesc)
883 RTUSBKickBulkOut(pAd);
884 #endif /* RTMP_MAC_USB // */
890 ========================================================================
892 Routine Description:
893 Calculates the duration which is required to transmit out frames
894 with given size and specified rate.
896 Arguments:
897 pAd Pointer to our adapter
898 Rate Transmit rate
899 Size Frame size in units of byte
901 Return Value:
902 Duration number in units of usec
904 IRQL = PASSIVE_LEVEL
905 IRQL = DISPATCH_LEVEL
907 Note:
909 ========================================================================
911 USHORT RTMPCalcDuration(IN PRTMP_ADAPTER pAd, IN UCHAR Rate, IN ULONG Size)
913 ULONG Duration = 0;
915 if (Rate < RATE_FIRST_OFDM_RATE) /* CCK */
917 if ((Rate > RATE_1)
918 && OPSTATUS_TEST_FLAG(pAd,
919 fOP_STATUS_SHORT_PREAMBLE_INUSED))
920 Duration = 96; /* 72+24 preamble+plcp */
921 else
922 Duration = 192; /* 144+48 preamble+plcp */
924 Duration += (USHORT) ((Size << 4) / RateIdTo500Kbps[Rate]);
925 if ((Size << 4) % RateIdTo500Kbps[Rate])
926 Duration++;
927 } else if (Rate <= RATE_LAST_OFDM_RATE) /* OFDM rates */
929 Duration = 20 + 6; /* 16+4 preamble+plcp + Signal Extension */
930 Duration +=
931 4 * (USHORT) ((11 + Size * 4) / RateIdTo500Kbps[Rate]);
932 if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
933 Duration += 4;
934 } else /*mimo rate */
936 Duration = 20 + 6; /* 16+4 preamble+plcp + Signal Extension */
939 return (USHORT) Duration;
943 ========================================================================
945 Routine Description:
946 Calculates the duration which is required to transmit out frames
947 with given size and specified rate.
949 Arguments:
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
957 Length Frame length
958 TxPreamble Short or Long preamble when using CCK rates
959 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
961 Return Value:
962 None
964 IRQL = PASSIVE_LEVEL
965 IRQL = DISPATCH_LEVEL
967 See also : BASmartHardTransmit() !!!
969 ========================================================================
971 VOID RTMPWriteTxWI(IN PRTMP_ADAPTER pAd, IN PTXWI_STRUC pOutTxWI, IN BOOLEAN FRAG, IN BOOLEAN CFACK, IN BOOLEAN InsTimestamp, IN BOOLEAN AMPDU, IN BOOLEAN Ack, IN BOOLEAN NSeq, /* HW new a sequence. */
972 IN UCHAR BASize,
973 IN UCHAR WCID,
974 IN ULONG Length,
975 IN UCHAR PID,
976 IN UCHAR TID,
977 IN UCHAR TxRate,
978 IN UCHAR Txopmode,
979 IN BOOLEAN CfAck, IN HTTRANSMIT_SETTING * pTransmit)
981 PMAC_TABLE_ENTRY pMac = NULL;
982 TXWI_STRUC TxWI;
983 PTXWI_STRUC pTxWI;
985 if (WCID < MAX_LEN_OF_MAC_TABLE)
986 pMac = &pAd->MacTab.Content[WCID];
988 /* */
989 /* Always use Long preamble before verifiation short preamble functionality works well. */
990 /* Todo: remove the following line if short preamble functionality works */
991 /* */
992 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
993 NdisZeroMemory(&TxWI, TXWI_SIZE);
994 pTxWI = &TxWI;
996 pTxWI->FRAG = FRAG;
998 pTxWI->CFACK = CFACK;
999 pTxWI->TS = InsTimestamp;
1000 pTxWI->AMPDU = AMPDU;
1001 pTxWI->ACK = Ack;
1002 pTxWI->txop = Txopmode;
1004 pTxWI->NSEQ = NSeq;
1005 /* John tune the performace with Intel Client in 20 MHz performance */
1006 BASize = pAd->CommonCfg.TxBASize;
1007 if (pAd->MACVersion == 0x28720200) {
1008 if (BASize > 13)
1009 BASize = 13;
1010 } else {
1011 if (BASize > 7)
1012 BASize = 7;
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 */
1023 pTxWI->BW =
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;
1031 if (pMac) {
1032 if (pAd->CommonCfg.bMIMOPSEnable) {
1033 if ((pMac->MmpsMode == MMPS_DYNAMIC)
1034 && (pTransmit->field.MCS > 7)) {
1035 /* Dynamic MIMO Power Save Mode */
1036 pTxWI->MIMOps = 1;
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) {
1041 pTxWI->MCS = 7;
1042 pTxWI->MIMOps = 0;
1046 /*pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0; */
1047 if (pMac->bIAmBadAtheros
1048 && (pMac->WepStatus != Ndis802_11WEPDisabled)) {
1049 pTxWI->MpduDensity = 7;
1050 } else {
1051 pTxWI->MpduDensity = pMac->MpduDensity;
1055 pTxWI->PacketId = pTxWI->MCS;
1056 NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC));
1059 VOID RTMPWriteTxWI_Data(IN PRTMP_ADAPTER pAd,
1060 IN OUT PTXWI_STRUC pTxWI, IN TX_BLK * pTxBlk)
1062 HTTRANSMIT_SETTING *pTransmit;
1063 PMAC_TABLE_ENTRY pMacEntry;
1064 UCHAR BASize;
1066 ASSERT(pTxWI);
1068 pTransmit = pTxBlk->pTransmit;
1069 pMacEntry = pTxBlk->pMacEntry;
1071 /* */
1072 /* Always use Long preamble before verifiation short preamble functionality works well. */
1073 /* Todo: remove the following line if short preamble functionality works */
1074 /* */
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 */
1088 pTxWI->BW =
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 UCHAR RABAOriIdx = 0; /*The RA's BA Originator table index. */
1098 RABAOriIdx =
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;
1111 if (pMacEntry) {
1112 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC)
1113 && (pTransmit->field.MCS > 7)) {
1114 /* Dynamic MIMO Power Save Mode */
1115 pTxWI->MIMOps = 1;
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) {
1120 pTxWI->MCS = 7;
1121 pTxWI->MIMOps = 0;
1125 if (pMacEntry->bIAmBadAtheros
1126 && (pMacEntry->WepStatus != Ndis802_11WEPDisabled)) {
1127 pTxWI->MpduDensity = 7;
1128 } else {
1129 pTxWI->MpduDensity = pMacEntry->MpduDensity;
1133 /* for rate adapation */
1134 pTxWI->PacketId = pTxWI->MCS;
1137 VOID RTMPWriteTxWI_Cache(IN PRTMP_ADAPTER pAd,
1138 IN OUT PTXWI_STRUC pTxWI, IN TX_BLK * pTxBlk)
1140 PHTTRANSMIT_SETTING /*pTxHTPhyMode, */ pTransmit;
1141 PMAC_TABLE_ENTRY pMacEntry;
1143 /* */
1144 /* update TXWI */
1145 /* */
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 */
1156 pTxWI->BW =
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);
1170 pTxWI->MIMOps = 0;
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 */
1177 pTxWI->MIMOps = 1;
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)) {
1182 pTxWI->MCS = 7;
1183 pTxWI->MIMOps = 0;
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(IN PRTMP_ADAPTER pAd,
1198 IN PUCHAR pPrevAddr1, IN PUCHAR p8023hdr)
1201 /* can't aggregate EAPOL (802.1x) frame */
1202 if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1203 return FALSE;
1205 /* can't aggregate multicast/broadcast frame */
1206 if (p8023hdr[0] & 0x01)
1207 return FALSE;
1209 if (INFRA_ON(pAd)) /* must be unicast to AP */
1210 return TRUE;
1211 else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) /* unicast to same STA */
1212 return TRUE;
1213 else
1214 return FALSE;
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.
1225 Arguments:
1227 Return Value:
1229 Note:
1231 ========================================================================
1233 BOOLEAN PeerIsAggreOn(IN PRTMP_ADAPTER pAd,
1234 IN ULONG TxRate, IN PMAC_TABLE_ENTRY pMacEntry)
1236 ULONG 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) {
1241 return TRUE;
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 */
1245 return TRUE;
1247 #endif /* AGGREGATION_SUPPORT // */
1250 return FALSE;
1255 ========================================================================
1257 Routine Description:
1258 Check and fine the packet waiting in SW queue with highest priority
1260 Arguments:
1261 pAd Pointer to our adapter
1263 Return Value:
1264 pQueue Pointer to Waiting Queue
1266 IRQL = DISPATCH_LEVEL
1268 Note:
1270 ========================================================================
1272 PQUEUE_HEADER RTMPCheckTxSwQueue(IN PRTMP_ADAPTER pAd, OUT PUCHAR pQueIdx)
1275 ULONG Number;
1276 /* 2004-11-15 to be removed. test aggregation only */
1277 /* if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2)) */
1278 /* return NULL; */
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;
1301 return (NULL);
1305 ========================================================================
1307 Routine Description:
1308 Suspend MSDU transmission
1310 Arguments:
1311 pAd Pointer to our adapter
1313 Return Value:
1314 None
1316 Note:
1318 ========================================================================
1320 VOID RTMPSuspendMsduTransmission(IN PRTMP_ADAPTER pAd)
1322 DBGPRINT(RT_DEBUG_TRACE, ("SCANNING, suspend MSDU transmission ...\n"));
1324 /* */
1325 /* Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and */
1326 /* use Lowbound as R66 value on ScanNextChannel(...) */
1327 /* */
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
1345 Arguments:
1346 pAd Pointer to our adapter
1348 Return Value:
1349 None
1351 IRQL = DISPATCH_LEVEL
1353 Note:
1355 ========================================================================
1357 VOID RTMPResumeMsduTransmission(IN PRTMP_ADAPTER pAd)
1359 /* UCHAR IrqState; */
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; */
1376 /* if (IrqState) */
1377 /* RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS); */
1378 /* else */
1379 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1382 UINT deaggregate_AMSDU_announce(IN PRTMP_ADAPTER pAd,
1383 PNDIS_PACKET pPacket,
1384 IN PUCHAR pData, IN ULONG DataSize)
1386 USHORT PayloadSize;
1387 USHORT SubFrameSize;
1388 PHEADER_802_3 pAMSDUsubheader;
1389 UINT nMSDU;
1390 UCHAR Header802_3[14];
1392 PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP;
1393 PNDIS_PACKET pClonePacket;
1395 nMSDU = 0;
1397 while (DataSize > LENGTH_802_3) {
1399 nMSDU++;
1401 /*hex_dump("subheader", pData, 64); */
1402 pAMSDUsubheader = (PHEADER_802_3) pData;
1403 /*pData += LENGTH_802_3; */
1404 PayloadSize =
1405 pAMSDUsubheader->Octet[1] +
1406 (pAMSDUsubheader->Octet[0] << 8);
1407 SubFrameSize = PayloadSize + LENGTH_802_3;
1409 if ((DataSize < SubFrameSize) || (PayloadSize > 1518)) {
1410 break;
1412 /*DBGPRINT(RT_DEBUG_TRACE,("%d subframe: Size = %d\n", nMSDU, PayloadSize)); */
1414 pPayload = pData + LENGTH_802_3;
1415 pDA = pData;
1416 pSA = pData + MAC_ADDR_LEN;
1418 /* convert to 802.3 header */
1419 CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize,
1420 pRemovedLLCSNAP);
1422 if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E)) {
1423 /* avoid local heap overflow, use dyanamic allocation */
1424 MLME_QUEUE_ELEM *Elem =
1425 (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM),
1426 MEM_ALLOC_FLAG);
1427 if (Elem != NULL) {
1428 memmove(Elem->Msg +
1429 (LENGTH_802_11 + LENGTH_802_1_H),
1430 pPayload, PayloadSize);
1431 Elem->MsgLen =
1432 LENGTH_802_11 + LENGTH_802_1_H +
1433 PayloadSize;
1434 /*WpaEAPOLKeyAction(pAd, Elem); */
1435 REPORT_MGMT_FRAME_TO_MLME(pAd, BSSID_WCID,
1436 Elem->Msg,
1437 Elem->MsgLen, 0, 0, 0,
1439 kfree(Elem);
1444 if (pRemovedLLCSNAP) {
1445 pPayload -= LENGTH_802_3;
1446 PayloadSize += LENGTH_802_3;
1447 NdisMoveMemory(pPayload, &Header802_3[0],
1448 LENGTH_802_3);
1452 pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
1453 if (pClonePacket) {
1454 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket,
1455 RTMP_GET_PACKET_IF
1456 (pPacket));
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) {
1464 break;
1467 if (DataSize > SubFrameSize) {
1468 pData += SubFrameSize;
1469 DataSize -= SubFrameSize;
1470 } else {
1471 /* end of A-MSDU */
1472 DataSize = 0;
1476 /* finally release original rx packet */
1477 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1479 return nMSDU;
1482 UINT BA_Reorder_AMSDU_Annnounce(IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPacket)
1484 PUCHAR pData;
1485 USHORT DataSize;
1486 UINT nMSDU = 0;
1488 pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
1489 DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
1491 nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
1493 return nMSDU;
1497 ==========================================================================
1498 Description:
1499 Look up the MAC address in the MAC table. Return NULL if not found.
1500 Return:
1501 pEntry - pointer to the MAC entry; NULL is not found
1502 ==========================================================================
1504 MAC_TABLE_ENTRY *MacTableLookup(IN PRTMP_ADAPTER pAd, PUCHAR pAddr)
1506 ULONG HashIdx;
1507 MAC_TABLE_ENTRY *pEntry = NULL;
1509 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1510 pEntry = pAd->MacTab.Hash[HashIdx];
1512 while (pEntry
1513 && (pEntry->ValidAsCLI || pEntry->ValidAsWDS
1514 || pEntry->ValidAsApCli || pEntry->ValidAsMesh)) {
1515 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) {
1516 break;
1517 } else
1518 pEntry = pEntry->pNext;
1521 return pEntry;
1524 MAC_TABLE_ENTRY *MacTableInsertEntry(IN PRTMP_ADAPTER pAd,
1525 IN PUCHAR pAddr,
1526 IN UCHAR apidx, IN BOOLEAN CleanAll)
1528 UCHAR HashIdx;
1529 int i, FirstWcid;
1530 MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
1531 /* USHORT offset; */
1532 /* ULONG addr; */
1534 /* if FULL, return */
1535 if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
1536 return NULL;
1538 FirstWcid = 1;
1540 if (pAd->StaCfg.BssType == BSS_INFRA)
1541 FirstWcid = 2;
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(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;
1572 pEntry->pAd = pAd;
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)
1582 pEntry->apidx =
1583 (apidx - MIN_NET_DEVICE_FOR_MESH);
1584 else if (pEntry->ValidAsApCli)
1585 pEntry->apidx =
1586 (apidx - MIN_NET_DEVICE_FOR_APCLI);
1587 else if (pEntry->ValidAsWDS)
1588 pEntry->apidx =
1589 (apidx - MIN_NET_DEVICE_FOR_WDS);
1590 else
1591 pEntry->apidx = apidx;
1595 pEntry->AuthMode = pAd->StaCfg.AuthMode;
1596 pEntry->WepStatus =
1597 pAd->StaCfg.WepStatus;
1598 pEntry->PrivacyFilter =
1599 Ndis802_11PrivFilterAcceptAll;
1600 #ifdef RTMP_MAC_PCI
1601 AsicRemovePairwiseKeyEntry(pAd,
1602 pEntry->
1603 apidx,
1604 (UCHAR) i);
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 = (USHORT) 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);
1627 pAd->MacTab.Size++;
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));
1634 break;
1638 /* add this MAC entry into HASH table */
1639 if (pEntry) {
1640 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1641 if (pAd->MacTab.Hash[HashIdx] == NULL) {
1642 pAd->MacTab.Hash[HashIdx] = pEntry;
1643 } else {
1644 pCurrEntry = pAd->MacTab.Hash[HashIdx];
1645 while (pCurrEntry->pNext != NULL)
1646 pCurrEntry = pCurrEntry->pNext;
1647 pCurrEntry->pNext = pEntry;
1651 NdisReleaseSpinLock(&pAd->MacTabLock);
1652 return pEntry;
1656 ==========================================================================
1657 Description:
1658 Delete a specified client from MAC table
1659 ==========================================================================
1661 BOOLEAN MacTableDeleteEntry(IN PRTMP_ADAPTER pAd,
1662 IN USHORT wcid, IN PUCHAR pAddr)
1664 USHORT HashIdx;
1665 MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
1666 BOOLEAN Cancelled;
1667 /*USHORT offset; // unused variable */
1668 /*UCHAR j; // unused variable */
1670 if (wcid >= MAX_LEN_OF_MAC_TABLE)
1671 return FALSE;
1673 NdisAcquireSpinLock(&pAd->MacTabLock);
1675 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1676 /*pEntry = pAd->MacTab.Hash[HashIdx]; */
1677 pEntry = &pAd->MacTab.Content[wcid];
1679 if (pEntry
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);
1690 pPrevEntry = NULL;
1691 pProbeEntry = pAd->MacTab.Hash[HashIdx];
1692 ASSERT(pProbeEntry);
1694 /* update Hash list */
1695 do {
1696 if (pProbeEntry == pEntry) {
1697 if (pPrevEntry == NULL) {
1698 pAd->MacTab.Hash[HashIdx] =
1699 pEntry->pNext;
1700 } else {
1701 pPrevEntry->pNext =
1702 pEntry->pNext;
1704 break;
1707 pPrevEntry = pProbeEntry;
1708 pProbeEntry = pProbeEntry->pNext;
1709 } while (pProbeEntry);
1711 /* not found !!! */
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,
1720 &Cancelled);
1721 pEntry->EnqueueEapolStartTimerRunning =
1722 EAPOL_START_DISABLE;
1725 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1726 pAd->MacTab.Size--;
1727 DBGPRINT(RT_DEBUG_TRACE,
1728 ("MacTableDeleteEntry1 - Total= %d\n",
1729 pAd->MacTab.Size));
1730 } else {
1731 DBGPRINT(RT_DEBUG_OFF,
1732 ("\n%s: Impossible Wcid = %d !!!!!\n",
1733 __func__, wcid));
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 */
1745 return TRUE;
1749 ==========================================================================
1750 Description:
1751 This routine reset the entire MAC table. All packets pending in
1752 the power-saving queues are freed here.
1753 ==========================================================================
1755 VOID MacTableReset(IN PRTMP_ADAPTER pAd)
1757 int i;
1759 DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
1760 /*NdisAcquireSpinLock(&pAd->MacTabLock); */
1762 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
1763 #ifdef RTMP_MAC_PCI
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;
1773 #ifdef RTMP_MAC_USB
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); */
1782 return;
1786 ==========================================================================
1787 Description:
1789 IRQL = DISPATCH_LEVEL
1791 ==========================================================================
1793 VOID AssocParmFill(IN PRTMP_ADAPTER pAd,
1794 IN OUT MLME_ASSOC_REQ_STRUCT * AssocReq,
1795 IN PUCHAR pAddr,
1796 IN USHORT CapabilityInfo,
1797 IN ULONG Timeout, IN USHORT 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 ==========================================================================
1808 Description:
1810 IRQL = DISPATCH_LEVEL
1812 ==========================================================================
1814 VOID DisassocParmFill(IN PRTMP_ADAPTER pAd,
1815 IN OUT MLME_DISASSOC_REQ_STRUCT * DisassocReq,
1816 IN PUCHAR pAddr, IN USHORT 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.
1829 Arguments:
1830 pAd Pointer to our adapter
1831 pPacket Pointer to outgoing Ndis frame
1833 Return Value:
1834 TRUE To be duplicate at Low data rate transmit. (1mb)
1835 FALSE Do nothing.
1837 IRQL = DISPATCH_LEVEL
1839 Note:
1841 MAC header + IP Header + UDP Header
1842 14 Bytes 20 Bytes
1844 UDP Header
1845 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
1846 Source Port
1847 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
1848 Destination Port
1850 port 0x43 means Bootstrap Protocol, server.
1851 Port 0x44 means Bootstrap Protocol, client.
1853 ========================================================================
1856 BOOLEAN RTMPCheckDHCPFrame(IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPacket)
1858 PACKET_INFO PacketInfo;
1859 ULONG NumberOfBytesRead = 0;
1860 ULONG CurrentOffset = 0;
1861 PVOID pVirtualAddress = NULL;
1862 UINT NdisBufferLength;
1863 PUCHAR pSrc;
1864 USHORT Protocol;
1865 UCHAR ByteOffset36 = 0;
1866 UCHAR ByteOffset38 = 0;
1867 BOOLEAN ReadFirstParm = TRUE;
1869 RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *) & pVirtualAddress,
1870 &NdisBufferLength);
1872 NumberOfBytesRead += NdisBufferLength;
1873 pSrc = (PUCHAR) pVirtualAddress;
1874 Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
1876 /* */
1877 /* Check DHCP & BOOTP protocol */
1878 /* */
1879 while (NumberOfBytesRead <= PacketInfo.TotalPacketLength) {
1880 if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE)) {
1881 CurrentOffset =
1882 35 - (NumberOfBytesRead - NdisBufferLength);
1883 ByteOffset36 = *(pSrc + CurrentOffset);
1884 ReadFirstParm = FALSE;
1887 if (NumberOfBytesRead >= 37) {
1888 CurrentOffset =
1889 37 - (NumberOfBytesRead - NdisBufferLength);
1890 ByteOffset38 = *(pSrc + CurrentOffset);
1891 /*End of Read */
1892 break;
1894 return FALSE;
1897 /* Check for DHCP & BOOTP protocol */
1898 if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43)) {
1899 /* */
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 */
1903 /* */
1904 if (Protocol != 0x0806)
1905 return FALSE;
1908 return TRUE;
1911 BOOLEAN RTMPCheckEtherType(IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPacket)
1913 USHORT TypeLen;
1914 UCHAR Byte0, Byte1;
1915 PUCHAR pSrcBuf;
1916 UINT32 pktLen;
1917 UINT16 srcPort, dstPort;
1918 BOOLEAN status = TRUE;
1920 pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
1921 pktLen = GET_OS_PKT_LEN(pPacket);
1923 ASSERT(pSrcBuf);
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((PNDIS_BUFFER) pSrcBuf, 6,
1942 &Byte0, &Byte1);
1943 RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
1944 TypeLen = (USHORT) ((Byte0 << 8) + Byte1);
1945 pSrcBuf += 8; /* Skip this LLC/SNAP header */
1946 } else {
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) +
1960 Pad (0-p bytes) +
1961 Frame Check Sequence (4-bytes) */
1963 RTMP_SET_PACKET_VLAN(pPacket, 1);
1964 Sniff2BytesFromNdisBuffer((PNDIS_BUFFER) pSrcBuf, 2, &Byte0,
1965 &Byte1);
1966 TypeLen = (USHORT) ((Byte0 << 8) + Byte1);
1968 pSrcBuf += 4; /* Skip the VLAN Header. */
1971 switch (TypeLen) {
1972 case 0x0800:
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 */
1979 srcPort =
1980 OS_NTOHS(get_unaligned
1981 ((PUINT16) (pSrcBuf)));
1982 dstPort =
1983 OS_NTOHS(get_unaligned
1984 ((PUINT16) (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);
1991 break;
1992 case 0x0806:
1994 /*ARP Packet. */
1995 RTMP_SET_PACKET_DHCP(pPacket, 1);
1997 break;
1998 case 0x888e:
2000 /* EAPOL Packet. */
2001 RTMP_SET_PACKET_EAPOL(pPacket, 1);
2003 break;
2004 default:
2005 status = FALSE;
2006 break;
2009 return status;
2013 VOID Update_Rssi_Sample(IN PRTMP_ADAPTER pAd,
2014 IN RSSI_SAMPLE * pRssi, IN PRXWI_STRUC pRxWI)
2016 CHAR rssi0 = pRxWI->RSSI0;
2017 CHAR rssi1 = pRxWI->RSSI1;
2018 CHAR rssi2 = pRxWI->RSSI2;
2020 if (rssi0 != 0) {
2021 pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR) rssi0, RSSI_0);
2022 pRssi->AvgRssi0X8 =
2023 (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
2024 pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
2027 if (rssi1 != 0) {
2028 pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR) rssi1, RSSI_1);
2029 pRssi->AvgRssi1X8 =
2030 (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
2031 pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
2034 if (rssi2 != 0) {
2035 pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR) rssi2, RSSI_2);
2036 pRssi->AvgRssi2X8 =
2037 (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
2038 pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
2042 /* Normal legacy Rx packet indication */
2043 VOID Indicate_Legacy_Packet(IN PRTMP_ADAPTER pAd,
2044 IN RX_BLK * pRxBlk, IN UCHAR FromWhichBSSID)
2046 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2047 UCHAR Header802_3[LENGTH_802_3];
2049 /* 1. get 802.3 Header */
2050 /* 2. remove LLC */
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);
2059 return;
2062 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
2064 #ifdef RTMP_MAC_USB
2065 if (pAd->CommonCfg.bDisableReordering == 0) {
2066 PBA_REC_ENTRY pBAEntry;
2067 ULONG Now32;
2068 UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID;
2069 UCHAR TID = pRxBlk->pRxWI->TID;
2070 USHORT Idx;
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];
2076 if (Idx != 0) {
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->
2083 LastIndSeqAtTimer
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",
2089 pRxBlk->Flags,
2090 pRxBlk->pRxWI->TID,
2091 pRxBlk->RxD.AMPDU));
2092 hex_dump("Dump the legacy Packet:",
2093 GET_OS_PKT_DATAPTR(pRxBlk->
2094 pRxPacket),
2095 64);
2096 ba_flush_reordering_timeout_mpdus(pAd,
2097 pBAEntry,
2098 Now32);
2103 #endif /* RTMP_MAC_USB // */
2105 wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2107 /* */
2108 /* pass this 802.3 packet to upper layer or forward this packet to WM directly */
2109 /* */
2110 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
2113 /* Normal, AMPDU or AMSDU */
2114 VOID CmmRxnonRalinkFrameIndicate(IN PRTMP_ADAPTER pAd,
2115 IN RX_BLK * pRxBlk, IN UCHAR FromWhichBSSID)
2117 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU)
2118 && (pAd->CommonCfg.bDisableReordering == 0)) {
2119 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2120 } else {
2121 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) {
2122 /* handle A-MSDU */
2123 Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2124 } else {
2125 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
2130 VOID CmmRxRalinkFrameIndicate(IN PRTMP_ADAPTER pAd,
2131 IN MAC_TABLE_ENTRY * pEntry,
2132 IN RX_BLK * pRxBlk, IN UCHAR FromWhichBSSID)
2134 UCHAR Header802_3[LENGTH_802_3];
2135 UINT16 Msdu2Size;
2136 UINT16 Payload1Size, Payload2Size;
2137 PUCHAR pData2;
2138 PNDIS_PACKET pPacket2 = NULL;
2140 Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData + 1) << 8);
2142 if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize)) {
2143 /* skip two byte MSDU2 len */
2144 pRxBlk->pData += 2;
2145 pRxBlk->DataSize -= 2;
2146 } else {
2147 /* release packet */
2148 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
2149 NDIS_STATUS_FAILURE);
2150 return;
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;
2165 pPacket2 =
2166 duplicate_pkt(pAd, (pData2 - LENGTH_802_3), LENGTH_802_3, pData2,
2167 Payload2Size, FromWhichBSSID);
2169 if (!pPacket2) {
2170 /* release packet */
2171 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
2172 NDIS_STATUS_FAILURE);
2173 return;
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,
2180 FromWhichBSSID);
2182 if (pPacket2) {
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 PNDIS_PACKET RTMPDeFragmentDataFrame(IN PRTMP_ADAPTER pAd, IN RX_BLK * pRxBlk)
2197 PHEADER_802_11 pHeader = pRxBlk->pHeader;
2198 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2199 UCHAR *pData = pRxBlk->pData;
2200 USHORT DataSize = pRxBlk->DataSize;
2201 PNDIS_PACKET pRetPacket = NULL;
2202 UCHAR *pFragBuffer = NULL;
2203 BOOLEAN bReassDone = FALSE;
2204 UCHAR HeaderRoom = 0;
2206 ASSERT(pHeader);
2208 HeaderRoom = pData - (UCHAR *) 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);
2216 pFragBuffer =
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 */
2244 /* */
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. */
2247 /* */
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,
2259 DataSize);
2260 pAd->FragFrame.RxSize += DataSize;
2261 pAd->FragFrame.LastFrag = pHeader->Frag; /* Update fragment number */
2263 /* Last fragment */
2264 if (pHeader->FC.MoreFrag == FALSE) {
2265 bReassDone = TRUE;
2269 done:
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 */
2275 if (bReassDone) {
2276 PNDIS_PACKET pNewFragPacket;
2278 /* allocate a new packet buffer for fragment */
2279 pNewFragPacket =
2280 RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
2281 if (pNewFragPacket) {
2282 /* update RxBlk */
2283 pRetPacket = pAd->FragFrame.pFragPacket;
2284 pAd->FragFrame.pFragPacket = pNewFragPacket;
2285 pRxBlk->pHeader =
2286 (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
2287 pRxBlk->pData = (UCHAR *) pRxBlk->pHeader + HeaderRoom;
2288 pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
2289 pRxBlk->pRxPacket = pRetPacket;
2290 } else {
2291 RESET_FRAGFRAME(pAd->FragFrame);
2295 return pRetPacket;
2298 VOID Indicate_AMSDU_Packet(IN PRTMP_ADAPTER pAd,
2299 IN RX_BLK * pRxBlk, IN UCHAR FromWhichBSSID)
2301 UINT nMSDU;
2303 update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
2304 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
2305 nMSDU =
2306 deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData,
2307 pRxBlk->DataSize);
2310 VOID Indicate_EAPOL_Packet(IN PRTMP_ADAPTER pAd,
2311 IN RX_BLK * pRxBlk, IN UCHAR FromWhichBSSID)
2313 MAC_TABLE_ENTRY *pEntry = NULL;
2316 pEntry = &pAd->MacTab.Content[BSSID_WCID];
2317 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
2318 return;
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);
2327 return;
2331 #define BCN_TBTT_OFFSET 64 /*defer 64 us */
2332 VOID ReSyncBeaconTime(IN PRTMP_ADAPTER pAd)
2335 UINT32 Offset;
2337 Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
2339 pAd->TbttTickCount++;
2341 /* */
2342 /* The updated BeaconInterval Value will affect Beacon Interval after two TBTT */
2343 /* beacasue the original BeaconInterval had been loaded into next TBTT_TIMER */
2344 /* */
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);
2350 } else {
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);