• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/staging/rt2860/common/
1/*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
7 *
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
9 *
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 *************************************************************************
26*/
27
28#include "../rt_config.h"
29
30u8 SNAP_802_1H[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
31u8 SNAP_BRIDGE_TUNNEL[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
32
33/* Add Cisco Aironet SNAP heade for CCX2 support */
34u8 SNAP_AIRONET[] = { 0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00 };
35u8 CKIP_LLC_SNAP[] = { 0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02 };
36u8 EAPOL_LLC_SNAP[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e };
37u8 EAPOL[] = { 0x88, 0x8e };
38u8 TPID[] = { 0x81, 0x00 };	/* VLAN related */
39
40u8 IPX[] = { 0x81, 0x37 };
41u8 APPLE_TALK[] = { 0x80, 0xf3 };
42
43u8 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 */
48
49u8 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 */
54};
55
56u8 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 */
60};
61
62u8 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 */
66};
67
68char *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" };
73
74u8 default_cwmin[] =
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}; */
77u8 default_sta_aifsn[] = { 3, 7, 2, 2 };
78
79u8 MapUserPriorityToAccessCategory[8] =
80    { QID_AC_BE, QID_AC_BK, QID_AC_BK, QID_AC_BE, QID_AC_VI, QID_AC_VI,
81QID_AC_VO, QID_AC_VO };
82
83/*
84	========================================================================
85
86	Routine Description:
87		API for MLME to transmit management frame to AP (BSS Mode)
88	or station (IBSS Mode)
89
90	Arguments:
91		pAd Pointer to our adapter
92		pData		Pointer to the outgoing 802.11 frame
93		Length		Size of outgoing management frame
94
95	Return Value:
96		NDIS_STATUS_FAILURE
97		NDIS_STATUS_PENDING
98		NDIS_STATUS_SUCCESS
99
100	IRQL = PASSIVE_LEVEL
101	IRQL = DISPATCH_LEVEL
102
103	Note:
104
105	========================================================================
106*/
107int MiniportMMRequest(struct rt_rtmp_adapter *pAd,
108			      u8 QueIdx, u8 *pData, u32 Length)
109{
110	void *pPacket;
111	int Status = NDIS_STATUS_SUCCESS;
112	unsigned long FreeNum;
113	u8 rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE];	/*RTMP_HW_HDR_LEN]; */
114#ifdef RTMP_MAC_PCI
115	unsigned long IrqFlags = 0;
116	u8 IrqState;
117#endif /* RTMP_MAC_PCI // */
118	BOOLEAN bUseDataQ = FALSE;
119	int retryCnt = 0;
120
121	ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
122
123	if ((QueIdx & MGMT_USE_QUEUE_FLAG) == MGMT_USE_QUEUE_FLAG) {
124		bUseDataQ = TRUE;
125		QueIdx &= (~MGMT_USE_QUEUE_FLAG);
126	}
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;
133	}
134	if (bUseDataQ && (!IrqState))
135		RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
136#endif /* RTMP_MAC_PCI // */
137
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;
147		}
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 // */
158		{
159			FreeNum = GET_MGMTRING_FREENO(pAd);
160		}
161
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						   (u8 *)& 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;
174			}
175			/*pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; */
176			/*pAd->CommonCfg.MlmeRate = RATE_2; */
177
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));
203				}
204			}
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));
210		}
211	} while (retryCnt > 0);
212
213#ifdef RTMP_MAC_PCI
214	if (bUseDataQ && (!IrqState))
215		RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
216#endif /* RTMP_MAC_PCI // */
217
218	return Status;
219}
220
221/*
222	========================================================================
223
224	Routine Description:
225		Copy frame from waiting queue into relative ring buffer and set
226	appropriate ASIC register to kick hardware transmit function
227
228	Arguments:
229		pAd Pointer to our adapter
230		pBuffer 	Pointer to	memory of outgoing frame
231		Length		Size of outgoing management frame
232
233	Return Value:
234		NDIS_STATUS_FAILURE
235		NDIS_STATUS_PENDING
236		NDIS_STATUS_SUCCESS
237
238	IRQL = PASSIVE_LEVEL
239	IRQL = DISPATCH_LEVEL
240
241	Note:
242
243	========================================================================
244*/
245int MlmeHardTransmit(struct rt_rtmp_adapter *pAd,
246			     u8 QueIdx, void *pPacket)
247{
248	struct rt_packet_info PacketInfo;
249	u8 *pSrcBufVA;
250	u32 SrcBufLen;
251	struct rt_header_802_11 * pHeader_802_11;
252
253	if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
254	    ) {
255		return NDIS_STATUS_FAILURE;
256	}
257
258	RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
259	if (pSrcBufVA == NULL)
260		return NDIS_STATUS_FAILURE;
261
262	pHeader_802_11 = (struct rt_header_802_11 *) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE);
263
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);
270
271}
272
273int MlmeHardTransmitMgmtRing(struct rt_rtmp_adapter *pAd,
274				     u8 QueIdx, void *pPacket)
275{
276	struct rt_packet_info PacketInfo;
277	u8 *pSrcBufVA;
278	u32 SrcBufLen;
279	struct rt_header_802_11 * pHeader_802_11;
280	BOOLEAN bAckRequired, bInsertTimestamp;
281	u8 MlmeRate;
282	struct rt_txwi * pFirstTxWI;
283	struct rt_mac_table_entry *pMacEntry = NULL;
284	u8 PID;
285
286	RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
287
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;
294	}
295
296	{
297		/* outgoing frame always wakeup PHY to prevent frame lost */
298		if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
299			AsicForceWakeup(pAd, TRUE);
300	}
301
302	pFirstTxWI = (struct rt_txwi *) (pSrcBufVA + TXINFO_SIZE);
303	pHeader_802_11 = (struct rt_header_802_11 *) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE);	/*TXWI_SIZE); */
304
305	if (pHeader_802_11->Addr1[0] & 0x01) {
306		MlmeRate = pAd->CommonCfg.BasicMlmeRate;
307	} else {
308		MlmeRate = pAd->CommonCfg.MlmeRate;
309	}
310
311	/* Verify Mlme rate for a / g bands. */
312	if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6))	/* 11A band */
313		MlmeRate = RATE_6;
314
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);
318	}
319
320	{
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;
328		}
329	}
330
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); */
337
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)) */
342	{
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;
352		}
353	}
354
355	bInsertTimestamp = FALSE;
356	if (pHeader_802_11->FC.Type == BTYPE_CNTL)	/* must be PS-POLL */
357	{
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;
362		}
363		bAckRequired = FALSE;
364	} else			/* BTYPE_MGMT or BTYPE_DATA(must be NULL frame) */
365	{
366		/*pAd->Sequence++; */
367		/*pHeader_802_11->Sequence = pAd->Sequence; */
368
369		if (pHeader_802_11->Addr1[0] & 0x01)	/* MULTICAST, BROADCAST */
370		{
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 */
386			}
387		}
388	}
389
390	pHeader_802_11->Sequence = pAd->Sequence++;
391	if (pAd->Sequence > 0xfff)
392		pAd->Sequence = 0;
393
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);
404	}
405
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	/* */
411
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; */
416
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;
419
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);
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			      (u8)pMacEntry->MaxHTPhyMode.field.MCS,
434			      IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
435	}
436
437	/* Now do hardware-depened kick out. */
438	HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen);
439
440	/* Make sure to release MGMT ring resource */
441/*      if (!IrqState) */
442	RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
443	return NDIS_STATUS_SUCCESS;
444}
445
446/********************************************************************************
447
448	New DeQueue Procedures.
449
450 ********************************************************************************/
451
452#define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) 				\
453			do{													\
454				if (bIntContext == FALSE)						\
455				RTMP_IRQ_LOCK((lock), IrqFlags);		\
456			}while(0)
457
458#define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags)				\
459			do{													\
460				if (bIntContext == FALSE)						\
461					RTMP_IRQ_UNLOCK((lock), IrqFlags);	\
462			}while(0)
463
464/*
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.
477
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.
483
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;
493
494					11N Rate :
495								No piggyback,	//pTxBlk->bPiggyBack = FALSE;
496
497								(1).AMSDU
498									pTxBlk->bWMM = TRUE;
499								(2).AMPDU
500									pTxBlk->bWMM = TRUE;
501								(3).Normal
502
503					B/G Rate :
504								(1).ARALINK
505
506								(2).Normal
507	========================================================================
508*/
509static u8 TxPktClassification(struct rt_rtmp_adapter *pAd, void *pPacket)
510{
511	u8 TxFrameType = TX_UNKOWN_FRAME;
512	u8 Wcid;
513	struct rt_mac_table_entry *pMacEntry = NULL;
514	BOOLEAN bHTRate = FALSE;
515
516	Wcid = RTMP_GET_PACKET_WCID(pPacket);
517	if (Wcid == MCAST_WCID) {	/* Handle for RA is Broadcast/Multicast Address. */
518		return TX_MCAST_FRAME;
519	}
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 */
525
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)))) !=
534			 0)
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;
546		}
547	}
548
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;
553
554	return TxFrameType;
555}
556
557BOOLEAN RTMP_FillTxBlkInfo(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
558{
559	struct rt_packet_info PacketInfo;
560	void *pPacket;
561	struct rt_mac_table_entry *pMacEntry = NULL;
562
563	pPacket = pTxBlk->pPacket;
564	RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader,
565			     &pTxBlk->SrcBufLen);
566
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 */
571
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);
576
577	/* Default to clear this flag */
578	TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS);
579
580	if (pTxBlk->Wcid == MCAST_WCID) {
581		pTxBlk->pMacEntry = NULL;
582		{
583			pTxBlk->pTransmit =
584			    &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
585		}
586
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);
593		}
594
595	} else {
596		pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
597		pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode;
598
599		pMacEntry = pTxBlk->pMacEntry;
600
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);
606
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);
612		}
613
614		{
615			{
616
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);
623
624/*                              if (pAd->StaCfg.bAutoTxRateSwitch) */
625/*                                      TX_BLK_SET_FLAG(pTxBlk, fTX_AutoRateSwitch); */
626			}
627		}
628
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;
633
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)))
641				{
642					TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
643					TX_BLK_SET_FLAG(pTxBlk,
644							fTX_bForceNonQoS);
645				}
646			}
647
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);
650			}
651
652			if (RTMP_GET_PACKET_MOREDATA(pPacket)) {
653				TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
654			}
655		} else if (pTxBlk->TxFrameType == TX_FRAG_FRAME) {
656			TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag);
657		}
658
659		pMacEntry->DebugTxCount++;
660	}
661
662	return TRUE;
663}
664
665BOOLEAN CanDoAggregateTransmit(struct rt_rtmp_adapter *pAd,
666			       char * pPacket, struct rt_tx_blk *pTxBlk)
667{
668
669	/*DBGPRINT(RT_DEBUG_TRACE, ("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType)); */
670
671	if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
672		return FALSE;
673
674	if (RTMP_GET_PACKET_DHCP(pPacket) ||
675	    RTMP_GET_PACKET_EAPOL(pPacket) || RTMP_GET_PACKET_WAI(pPacket))
676		return FALSE;
677
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;
680	}
681
682	if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) && (pTxBlk->TxPacketList.Number == 2)) {	/* For RALINK-Aggregation, allow two frames in one batch. */
683		return FALSE;
684	}
685
686	if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))	/* must be unicast to AP */
687		return TRUE;
688	else
689		return FALSE;
690
691}
692
693/*
694	========================================================================
695
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.
701
702	Arguments:
703		pAd Pointer to our adapter
704		pQueue		Pointer to Waiting Queue
705
706	Return Value:
707		None
708
709	IRQL = DISPATCH_LEVEL
710
711	Note:
712
713	========================================================================
714*/
715void RTMPDeQueuePacket(struct rt_rtmp_adapter *pAd, IN BOOLEAN bIntContext, u8 QIdx,	/* BulkOutPipeId */
716		       u8 Max_Tx_Packets)
717{
718	struct rt_queue_entry *pEntry = NULL;
719	void *pPacket;
720	int Status = NDIS_STATUS_SUCCESS;
721	u8 Count = 0;
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;
729
730	if (QIdx == NUM_OF_TX_RING) {
731		sQIdx = 0;
732		eQIdx = 3;	/* 4 ACs, start from 0. */
733	} else {
734		sQIdx = eQIdx = QIdx;
735	}
736
737	for (QueIdx = sQIdx; QueIdx <= eQIdx; QueIdx++) {
738		Count = 0;
739
740		RTMP_START_DEQUEUE(pAd, QueIdx, IrqFlags);
741
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;
752			}
753
754			if (Count >= Max_Tx_Packets)
755				break;
756
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;
762			}
763#ifdef RTMP_MAC_PCI
764			FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
765
766			if (FreeNumber[QueIdx] <= 5) {
767				/* free Tx(QueIdx) resources */
768				RTMPFreeTXDUponTxDmaDone(pAd, QueIdx);
769				FreeNumber[QueIdx] =
770				    GET_TXRING_FREENO(pAd, QueIdx);
771			}
772#endif /* RTMP_MAC_PCI // */
773
774			/* probe the Queue Head */
775			pQueue = &pAd->TxSwQueue[QueIdx];
776			pEntry = pQueue->Head;
777			if (pEntry == NULL) {
778				DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext,
779					       IrqFlags);
780				break;
781			}
782
783			pTxBlk = &TxBlk;
784			NdisZeroMemory((u8 *)pTxBlk, sizeof(struct rt_tx_blk));
785			/*InitializeQueueHeader(&pTxBlk->TxPacketList);         // Didn't need it because we already memzero it. */
786			pTxBlk->QueIdx = QueIdx;
787
788			pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
789
790			/* Early check to make sure we have enoguh Tx Resource. */
791			hasTxDesc =
792			    RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk,
793						      FreeNumber[QueIdx],
794						      pPacket);
795			if (!hasTxDesc) {
796				pAd->PrivateInfo.TxRingFullCnt++;
797
798				DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext,
799					       IrqFlags);
800
801				break;
802			}
803
804			pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
805			pEntry = RemoveHeadQueue(pQueue);
806			pTxBlk->TotalFrameNum++;
807			pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket);	/* The real fragment number maybe vary */
808			pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
809			pTxBlk->pPacket = pPacket;
810			InsertTailQueue(&pTxBlk->TxPacketList,
811					PACKET_TO_QUEUE_ENTRY(pPacket));
812
813			if (pTxBlk->TxFrameType == TX_RALINK_FRAME
814			    || pTxBlk->TxFrameType == TX_AMSDU_FRAME) {
815				/* Enhance SW Aggregation Mechanism */
816				if (NEED_QUEUE_BACK_FOR_AGG
817				    (pAd, QueIdx, FreeNumber[QueIdx],
818				     pTxBlk->TxFrameType)) {
819					InsertHeadQueue(pQueue,
820							PACKET_TO_QUEUE_ENTRY
821							(pPacket));
822					DEQUEUE_UNLOCK(&pAd->irq_lock,
823						       bIntContext, IrqFlags);
824					break;
825				}
826
827				do {
828					pEntry = pQueue->Head;
829					if (pEntry == NULL)
830						break;
831
832					/* For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation. */
833					pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
834					FreeNumber[QueIdx] =
835					    GET_TXRING_FREENO(pAd, QueIdx);
836					hasTxDesc =
837					    RTMP_HAS_ENOUGH_FREE_DESC(pAd,
838								      pTxBlk,
839								      FreeNumber
840								      [QueIdx],
841								      pPacket);
842					if ((hasTxDesc == FALSE)
843					    ||
844					    (CanDoAggregateTransmit
845					     (pAd, pPacket, pTxBlk) == FALSE))
846						break;
847
848					/*Remove the packet from the TxSwQueue and insert into pTxBlk */
849					pEntry = RemoveHeadQueue(pQueue);
850					ASSERT(pEntry);
851					pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
852					pTxBlk->TotalFrameNum++;
853					pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket);	/* The real fragment number maybe vary */
854					pTxBlk->TotalFrameLen +=
855					    GET_OS_PKT_LEN(pPacket);
856					InsertTailQueue(&pTxBlk->TxPacketList,
857							PACKET_TO_QUEUE_ENTRY
858							(pPacket));
859				} while (1);
860
861				if (pTxBlk->TxPacketList.Number == 1)
862					pTxBlk->TxFrameType = TX_LEGACY_FRAME;
863			}
864#ifdef RTMP_MAC_USB
865			DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
866#endif /* RTMP_MAC_USB // */
867			Count += pTxBlk->TxPacketList.Number;
868
869			/* Do HardTransmit now. */
870			Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
871
872#ifdef RTMP_MAC_PCI
873			DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
874			/* static rate also need NICUpdateFifoStaCounters() function. */
875			/*if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */
876			NICUpdateFifoStaCounters(pAd);
877#endif /* RTMP_MAC_PCI // */
878
879		}
880
881		RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
882
883#ifdef RTMP_MAC_USB
884		if (!hasTxDesc)
885			RTUSBKickBulkOut(pAd);
886#endif /* RTMP_MAC_USB // */
887	}
888
889}
890
891/*
892	========================================================================
893
894	Routine Description:
895		Calculates the duration which is required to transmit out frames
896	with given size and specified rate.
897
898	Arguments:
899		pAd 	Pointer to our adapter
900		Rate			Transmit rate
901		Size			Frame size in units of byte
902
903	Return Value:
904		Duration number in units of usec
905
906	IRQL = PASSIVE_LEVEL
907	IRQL = DISPATCH_LEVEL
908
909	Note:
910
911	========================================================================
912*/
913u16 RTMPCalcDuration(struct rt_rtmp_adapter *pAd, u8 Rate, unsigned long Size)
914{
915	unsigned long Duration = 0;
916
917	if (Rate < RATE_FIRST_OFDM_RATE)	/* CCK */
918	{
919		if ((Rate > RATE_1)
920		    && OPSTATUS_TEST_FLAG(pAd,
921					  fOP_STATUS_SHORT_PREAMBLE_INUSED))
922			Duration = 96;	/* 72+24 preamble+plcp */
923		else
924			Duration = 192;	/* 144+48 preamble+plcp */
925
926		Duration += (u16)((Size << 4) / RateIdTo500Kbps[Rate]);
927		if ((Size << 4) % RateIdTo500Kbps[Rate])
928			Duration++;
929	} else if (Rate <= RATE_LAST_OFDM_RATE)	/* OFDM rates */
930	{
931		Duration = 20 + 6;	/* 16+4 preamble+plcp + Signal Extension */
932		Duration +=
933		    4 * (u16)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
934		if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
935			Duration += 4;
936	} else			/*mimo rate */
937	{
938		Duration = 20 + 6;	/* 16+4 preamble+plcp + Signal Extension */
939	}
940
941	return (u16)Duration;
942}
943
944/*
945	========================================================================
946
947	Routine Description:
948		Calculates the duration which is required to transmit out frames
949	with given size and specified rate.
950
951	Arguments:
952		pTxWI		Pointer to head of each MPDU to HW.
953		Ack 		Setting for Ack requirement bit
954		Fragment	Setting for Fragment bit
955		RetryMode	Setting for retry mode
956		Ifs 		Setting for IFS gap
957		Rate		Setting for transmit rate
958		Service 	Setting for service
959		Length		Frame length
960		TxPreamble	Short or Long preamble when using CCK rates
961		QueIdx - 0-3, according to 802.11e/d4.4 June/2003
962
963	Return Value:
964		None
965
966	IRQL = PASSIVE_LEVEL
967	IRQL = DISPATCH_LEVEL
968
969    See also : BASmartHardTransmit()    !
970
971	========================================================================
972*/
973void 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		   u8 BASize,
975		   u8 WCID,
976		   unsigned long Length,
977		   u8 PID,
978		   u8 TID,
979		   u8 TxRate,
980		   u8 Txopmode,
981		   IN BOOLEAN CfAck, IN HTTRANSMIT_SETTING * pTransmit)
982{
983	struct rt_mac_table_entry *pMac = NULL;
984	struct rt_txwi TxWI;
985	struct rt_txwi * pTxWI;
986
987	if (WCID < MAX_LEN_OF_MAC_TABLE)
988		pMac = &pAd->MacTab.Content[WCID];
989
990	/* */
991	/* Always use Long preamble before verifiation short preamble functionality works well. */
992	/* Todo: remove the following line if short preamble functionality works */
993	/* */
994	OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
995	NdisZeroMemory(&TxWI, TXWI_SIZE);
996	pTxWI = &TxWI;
997
998	pTxWI->FRAG = FRAG;
999
1000	pTxWI->CFACK = CFACK;
1001	pTxWI->TS = InsTimestamp;
1002	pTxWI->AMPDU = AMPDU;
1003	pTxWI->ACK = Ack;
1004	pTxWI->txop = Txopmode;
1005
1006	pTxWI->NSEQ = NSeq;
1007	/* John tune the performace with Intel Client in 20 MHz performance */
1008	BASize = pAd->CommonCfg.TxBASize;
1009	if (pAd->MACVersion == 0x28720200) {
1010		if (BASize > 13)
1011			BASize = 13;
1012	} else {
1013		if (BASize > 7)
1014			BASize = 7;
1015	}
1016	pTxWI->BAWinSize = BASize;
1017	pTxWI->ShortGI = pTransmit->field.ShortGI;
1018	pTxWI->STBC = pTransmit->field.STBC;
1019
1020	pTxWI->WirelessCliID = WCID;
1021	pTxWI->MPDUtotalByteCount = Length;
1022	pTxWI->PacketId = PID;
1023
1024	/* If CCK or OFDM, BW must be 20 */
1025	pTxWI->BW =
1026	    (pTransmit->field.MODE <=
1027	     MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1028
1029	pTxWI->MCS = pTransmit->field.MCS;
1030	pTxWI->PHYMODE = pTransmit->field.MODE;
1031	pTxWI->CFACK = CfAck;
1032
1033	if (pMac) {
1034		if (pAd->CommonCfg.bMIMOPSEnable) {
1035			if ((pMac->MmpsMode == MMPS_DYNAMIC)
1036			    && (pTransmit->field.MCS > 7)) {
1037				/* Dynamic MIMO Power Save Mode */
1038				pTxWI->MIMOps = 1;
1039			} else if (pMac->MmpsMode == MMPS_STATIC) {
1040				/* Static MIMO Power Save Mode */
1041				if (pTransmit->field.MODE >= MODE_HTMIX
1042				    && pTransmit->field.MCS > 7) {
1043					pTxWI->MCS = 7;
1044					pTxWI->MIMOps = 0;
1045				}
1046			}
1047		}
1048		/*pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0; */
1049		if (pMac->bIAmBadAtheros
1050		    && (pMac->WepStatus != Ndis802_11WEPDisabled)) {
1051			pTxWI->MpduDensity = 7;
1052		} else {
1053			pTxWI->MpduDensity = pMac->MpduDensity;
1054		}
1055	}
1056
1057	pTxWI->PacketId = pTxWI->MCS;
1058	NdisMoveMemory(pOutTxWI, &TxWI, sizeof(struct rt_txwi));
1059}
1060
1061void RTMPWriteTxWI_Data(struct rt_rtmp_adapter *pAd,
1062			struct rt_txwi * pTxWI, struct rt_tx_blk *pTxBlk)
1063{
1064	HTTRANSMIT_SETTING *pTransmit;
1065	struct rt_mac_table_entry *pMacEntry;
1066	u8 BASize;
1067
1068	ASSERT(pTxWI);
1069
1070	pTransmit = pTxBlk->pTransmit;
1071	pMacEntry = pTxBlk->pMacEntry;
1072
1073	/* */
1074	/* Always use Long preamble before verifiation short preamble functionality works well. */
1075	/* Todo: remove the following line if short preamble functionality works */
1076	/* */
1077	OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1078	NdisZeroMemory(pTxWI, TXWI_SIZE);
1079
1080	pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1081	pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1082	pTxWI->txop = pTxBlk->FrameGap;
1083
1084	pTxWI->WirelessCliID = pTxBlk->Wcid;
1085
1086	pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1087	pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
1088
1089	/* If CCK or OFDM, BW must be 20 */
1090	pTxWI->BW =
1091	    (pTransmit->field.MODE <=
1092	     MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1093	pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
1094
1095	/* John tune the performace with Intel Client in 20 MHz performance */
1096	BASize = pAd->CommonCfg.TxBASize;
1097	if ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry)) {
1098		u8 RABAOriIdx = 0;	/*The RA's BA Originator table index. */
1099
1100		RABAOriIdx =
1101		    pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
1102		BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1103	}
1104
1105	pTxWI->TxBF = pTransmit->field.TxBF;
1106	pTxWI->BAWinSize = BASize;
1107	pTxWI->ShortGI = pTransmit->field.ShortGI;
1108	pTxWI->STBC = pTransmit->field.STBC;
1109
1110	pTxWI->MCS = pTransmit->field.MCS;
1111	pTxWI->PHYMODE = pTransmit->field.MODE;
1112
1113	if (pMacEntry) {
1114		if ((pMacEntry->MmpsMode == MMPS_DYNAMIC)
1115		    && (pTransmit->field.MCS > 7)) {
1116			/* Dynamic MIMO Power Save Mode */
1117			pTxWI->MIMOps = 1;
1118		} else if (pMacEntry->MmpsMode == MMPS_STATIC) {
1119			/* Static MIMO Power Save Mode */
1120			if (pTransmit->field.MODE >= MODE_HTMIX
1121			    && pTransmit->field.MCS > 7) {
1122				pTxWI->MCS = 7;
1123				pTxWI->MIMOps = 0;
1124			}
1125		}
1126
1127		if (pMacEntry->bIAmBadAtheros
1128		    && (pMacEntry->WepStatus != Ndis802_11WEPDisabled)) {
1129			pTxWI->MpduDensity = 7;
1130		} else {
1131			pTxWI->MpduDensity = pMacEntry->MpduDensity;
1132		}
1133	}
1134
1135	/* for rate adapation */
1136	pTxWI->PacketId = pTxWI->MCS;
1137}
1138
1139void RTMPWriteTxWI_Cache(struct rt_rtmp_adapter *pAd,
1140			 struct rt_txwi * pTxWI, struct rt_tx_blk *pTxBlk)
1141{
1142	PHTTRANSMIT_SETTING /*pTxHTPhyMode, */ pTransmit;
1143	struct rt_mac_table_entry *pMacEntry;
1144
1145	/* */
1146	/* update TXWI */
1147	/* */
1148	pMacEntry = pTxBlk->pMacEntry;
1149	pTransmit = pTxBlk->pTransmit;
1150
1151	/*if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */
1152	/*if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pMacEntry)) */
1153	/*if (TX_BLK_TEST_FLAG(pTxBlk, fTX_AutoRateSwitch)) */
1154	if (pMacEntry->bAutoTxRateSwitch) {
1155		pTxWI->txop = IFS_HTTXOP;
1156
1157		/* If CCK or OFDM, BW must be 20 */
1158		pTxWI->BW =
1159		    (pTransmit->field.MODE <=
1160		     MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1161		pTxWI->ShortGI = pTransmit->field.ShortGI;
1162		pTxWI->STBC = pTransmit->field.STBC;
1163
1164		pTxWI->MCS = pTransmit->field.MCS;
1165		pTxWI->PHYMODE = pTransmit->field.MODE;
1166
1167		/* set PID for TxRateSwitching */
1168		pTxWI->PacketId = pTransmit->field.MCS;
1169	}
1170
1171	pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE : FALSE);
1172	pTxWI->MIMOps = 0;
1173
1174	if (pAd->CommonCfg.bMIMOPSEnable) {
1175		/* MIMO Power Save Mode */
1176		if ((pMacEntry->MmpsMode == MMPS_DYNAMIC)
1177		    && (pTransmit->field.MCS > 7)) {
1178			/* Dynamic MIMO Power Save Mode */
1179			pTxWI->MIMOps = 1;
1180		} else if (pMacEntry->MmpsMode == MMPS_STATIC) {
1181			/* Static MIMO Power Save Mode */
1182			if ((pTransmit->field.MODE >= MODE_HTMIX)
1183			    && (pTransmit->field.MCS > 7)) {
1184				pTxWI->MCS = 7;
1185				pTxWI->MIMOps = 0;
1186			}
1187		}
1188	}
1189
1190	pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1191
1192}
1193
1194/* should be called only when - */
1195/* 1. MEADIA_CONNECTED */
1196/* 2. AGGREGATION_IN_USED */
1197/* 3. Fragmentation not in used */
1198/* 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible */
1199BOOLEAN TxFrameIsAggregatible(struct rt_rtmp_adapter *pAd,
1200			      u8 *pPrevAddr1, u8 *p8023hdr)
1201{
1202
1203	/* can't aggregate EAPOL (802.1x) frame */
1204	if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1205		return FALSE;
1206
1207	/* can't aggregate multicast/broadcast frame */
1208	if (p8023hdr[0] & 0x01)
1209		return FALSE;
1210
1211	if (INFRA_ON(pAd))	/* must be unicast to AP */
1212		return TRUE;
1213	else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr))	/* unicast to same STA */
1214		return TRUE;
1215	else
1216		return FALSE;
1217}
1218
1219/*
1220	========================================================================
1221
1222	Routine Description:
1223	   Check the MSDU Aggregation policy
1224	1.HT aggregation is A-MSDU
1225	2.legaacy rate aggregation is software aggregation by Ralink.
1226
1227	Arguments:
1228
1229	Return Value:
1230
1231	Note:
1232
1233	========================================================================
1234*/
1235BOOLEAN PeerIsAggreOn(struct rt_rtmp_adapter *pAd,
1236		      unsigned long TxRate, struct rt_mac_table_entry *pMacEntry)
1237{
1238	unsigned long AFlags =
1239	    (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
1240
1241	if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags)) {
1242		if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) {
1243			return TRUE;
1244		}
1245#ifdef AGGREGATION_SUPPORT
1246		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			return TRUE;
1248		}
1249#endif /* AGGREGATION_SUPPORT // */
1250	}
1251
1252	return FALSE;
1253
1254}
1255
1256/*
1257	========================================================================
1258
1259	Routine Description:
1260		Check and fine the packet waiting in SW queue with highest priority
1261
1262	Arguments:
1263		pAd Pointer to our adapter
1264
1265	Return Value:
1266		pQueue		Pointer to Waiting Queue
1267
1268	IRQL = DISPATCH_LEVEL
1269
1270	Note:
1271
1272	========================================================================
1273*/
1274struct rt_queue_header *RTMPCheckTxSwQueue(struct rt_rtmp_adapter *pAd, u8 *pQueIdx)
1275{
1276
1277	unsigned long Number;
1278	/* 2004-11-15 to be removed. test aggregation only */
1279/*      if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2)) */
1280/*               return NULL; */
1281
1282	Number = pAd->TxSwQueue[QID_AC_BK].Number
1283	    + pAd->TxSwQueue[QID_AC_BE].Number
1284	    + pAd->TxSwQueue[QID_AC_VI].Number
1285	    + pAd->TxSwQueue[QID_AC_VO].Number;
1286
1287	if (pAd->TxSwQueue[QID_AC_VO].Head != NULL) {
1288		*pQueIdx = QID_AC_VO;
1289		return (&pAd->TxSwQueue[QID_AC_VO]);
1290	} else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL) {
1291		*pQueIdx = QID_AC_VI;
1292		return (&pAd->TxSwQueue[QID_AC_VI]);
1293	} else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL) {
1294		*pQueIdx = QID_AC_BE;
1295		return (&pAd->TxSwQueue[QID_AC_BE]);
1296	} else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL) {
1297		*pQueIdx = QID_AC_BK;
1298		return (&pAd->TxSwQueue[QID_AC_BK]);
1299	}
1300	/* No packet pending in Tx Sw queue */
1301	*pQueIdx = QID_AC_BK;
1302
1303	return (NULL);
1304}
1305
1306/*
1307	========================================================================
1308
1309	Routine Description:
1310		Suspend MSDU transmission
1311
1312	Arguments:
1313		pAd 	Pointer to our adapter
1314
1315	Return Value:
1316		None
1317
1318	Note:
1319
1320	========================================================================
1321*/
1322void RTMPSuspendMsduTransmission(struct rt_rtmp_adapter *pAd)
1323{
1324	DBGPRINT(RT_DEBUG_TRACE, ("SCANNING, suspend MSDU transmission ...\n"));
1325
1326	/* */
1327	/* Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and */
1328	/* use Lowbound as R66 value on ScanNextChannel(...) */
1329	/* */
1330	RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66,
1331				    &pAd->BbpTuning.R66CurrentValue);
1332
1333	/* set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning) */
1334	/*RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd))); */
1335	RTMPSetAGCInitValue(pAd, BW_20);
1336
1337	RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1338	/*RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000);                // abort all TX rings */
1339}
1340
1341/*
1342	========================================================================
1343
1344	Routine Description:
1345		Resume MSDU transmission
1346
1347	Arguments:
1348		pAd 	Pointer to our adapter
1349
1350	Return Value:
1351		None
1352
1353	IRQL = DISPATCH_LEVEL
1354
1355	Note:
1356
1357	========================================================================
1358*/
1359void RTMPResumeMsduTransmission(struct rt_rtmp_adapter *pAd)
1360{
1361/*    u8                     IrqState; */
1362
1363	DBGPRINT(RT_DEBUG_TRACE, ("SCAN done, resume MSDU transmission ...\n"));
1364
1365	/* After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value */
1366	/* R66 should not be 0 */
1367	if (pAd->BbpTuning.R66CurrentValue == 0) {
1368		pAd->BbpTuning.R66CurrentValue = 0x38;
1369		DBGPRINT_ERR(("RTMPResumeMsduTransmission, R66CurrentValue=0...\n"));
1370	}
1371
1372	RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66,
1373				     pAd->BbpTuning.R66CurrentValue);
1374
1375	RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1376/* sample, for IRQ LOCK to SEM LOCK */
1377/*    IrqState = pAd->irq_disabled; */
1378/*      if (IrqState) */
1379/*              RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS); */
1380/*    else */
1381	RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1382}
1383
1384u32 deaggregate_AMSDU_announce(struct rt_rtmp_adapter *pAd,
1385				void *pPacket,
1386				u8 *pData, unsigned long DataSize)
1387{
1388	u16 PayloadSize;
1389	u16 SubFrameSize;
1390	struct rt_header_802_3 * pAMSDUsubheader;
1391	u32 nMSDU;
1392	u8 Header802_3[14];
1393
1394	u8 *pPayload, *pDA, *pSA, *pRemovedLLCSNAP;
1395	void *pClonePacket;
1396
1397	nMSDU = 0;
1398
1399	while (DataSize > LENGTH_802_3) {
1400
1401		nMSDU++;
1402
1403		/*hex_dump("subheader", pData, 64); */
1404		pAMSDUsubheader = (struct rt_header_802_3 *) pData;
1405		/*pData += LENGTH_802_3; */
1406		PayloadSize =
1407		    pAMSDUsubheader->Octet[1] +
1408		    (pAMSDUsubheader->Octet[0] << 8);
1409		SubFrameSize = PayloadSize + LENGTH_802_3;
1410
1411		if ((DataSize < SubFrameSize) || (PayloadSize > 1518)) {
1412			break;
1413		}
1414		/*DBGPRINT(RT_DEBUG_TRACE,("%d subframe: Size = %d\n",  nMSDU, PayloadSize)); */
1415
1416		pPayload = pData + LENGTH_802_3;
1417		pDA = pData;
1418		pSA = pData + MAC_ADDR_LEN;
1419
1420		/* convert to 802.3 header */
1421		CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize,
1422				 pRemovedLLCSNAP);
1423
1424		if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E)) {
1425			/* avoid local heap overflow, use dyanamic allocation */
1426			struct rt_mlme_queue_elem *Elem =
1427			    kmalloc(sizeof(struct rt_mlme_queue_elem),
1428							MEM_ALLOC_FLAG);
1429			if (Elem != NULL) {
1430				memmove(Elem->Msg +
1431					(LENGTH_802_11 + LENGTH_802_1_H),
1432					pPayload, PayloadSize);
1433				Elem->MsgLen =
1434				    LENGTH_802_11 + LENGTH_802_1_H +
1435				    PayloadSize;
1436				/*WpaEAPOLKeyAction(pAd, Elem); */
1437				REPORT_MGMT_FRAME_TO_MLME(pAd, BSSID_WCID,
1438							  Elem->Msg,
1439							  Elem->MsgLen, 0, 0, 0,
1440							  0);
1441				kfree(Elem);
1442			}
1443		}
1444
1445		{
1446			if (pRemovedLLCSNAP) {
1447				pPayload -= LENGTH_802_3;
1448				PayloadSize += LENGTH_802_3;
1449				NdisMoveMemory(pPayload, &Header802_3[0],
1450					       LENGTH_802_3);
1451			}
1452		}
1453
1454		pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
1455		if (pClonePacket) {
1456			ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket,
1457							 RTMP_GET_PACKET_IF
1458							 (pPacket));
1459		}
1460
1461		/* A-MSDU has padding to multiple of 4 including subframe header. */
1462		/* align SubFrameSize up to multiple of 4 */
1463		SubFrameSize = (SubFrameSize + 3) & (~0x3);
1464
1465		if (SubFrameSize > 1528 || SubFrameSize < 32) {
1466			break;
1467		}
1468
1469		if (DataSize > SubFrameSize) {
1470			pData += SubFrameSize;
1471			DataSize -= SubFrameSize;
1472		} else {
1473			/* end of A-MSDU */
1474			DataSize = 0;
1475		}
1476	}
1477
1478	/* finally release original rx packet */
1479	RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1480
1481	return nMSDU;
1482}
1483
1484u32 BA_Reorder_AMSDU_Annnounce(struct rt_rtmp_adapter *pAd, void *pPacket)
1485{
1486	u8 *pData;
1487	u16 DataSize;
1488	u32 nMSDU = 0;
1489
1490	pData = (u8 *)GET_OS_PKT_DATAPTR(pPacket);
1491	DataSize = (u16)GET_OS_PKT_LEN(pPacket);
1492
1493	nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
1494
1495	return nMSDU;
1496}
1497
1498/*
1499	==========================================================================
1500	Description:
1501		Look up the MAC address in the MAC table. Return NULL if not found.
1502	Return:
1503		pEntry - pointer to the MAC entry; NULL is not found
1504	==========================================================================
1505*/
1506struct rt_mac_table_entry *MacTableLookup(struct rt_rtmp_adapter *pAd, u8 *pAddr)
1507{
1508	unsigned long HashIdx;
1509	struct rt_mac_table_entry *pEntry = NULL;
1510
1511	HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1512	pEntry = pAd->MacTab.Hash[HashIdx];
1513
1514	while (pEntry
1515	       && (pEntry->ValidAsCLI || pEntry->ValidAsWDS
1516		   || pEntry->ValidAsApCli || pEntry->ValidAsMesh)) {
1517		if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) {
1518			break;
1519		} else
1520			pEntry = pEntry->pNext;
1521	}
1522
1523	return pEntry;
1524}
1525
1526struct rt_mac_table_entry *MacTableInsertEntry(struct rt_rtmp_adapter *pAd,
1527				     u8 *pAddr,
1528				     u8 apidx, IN BOOLEAN CleanAll)
1529{
1530	u8 HashIdx;
1531	int i, FirstWcid;
1532	struct rt_mac_table_entry *pEntry = NULL, *pCurrEntry;
1533/*      u16  offset; */
1534/*      unsigned long   addr; */
1535
1536	/* if FULL, return */
1537	if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
1538		return NULL;
1539
1540	FirstWcid = 1;
1541
1542	if (pAd->StaCfg.BssType == BSS_INFRA)
1543		FirstWcid = 2;
1544
1545	/* allocate one MAC entry */
1546	NdisAcquireSpinLock(&pAd->MacTabLock);
1547	for (i = FirstWcid; i < MAX_LEN_OF_MAC_TABLE; i++)	/* skip entry#0 so that "entry index == AID" for fast lookup */
1548	{
1549		/* pick up the first available vacancy */
1550		if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
1551		    (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
1552		    (pAd->MacTab.Content[i].ValidAsApCli == FALSE) &&
1553		    (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
1554		    ) {
1555			pEntry = &pAd->MacTab.Content[i];
1556			if (CleanAll == TRUE) {
1557				pEntry->MaxSupportedRate = RATE_11;
1558				pEntry->CurrTxRate = RATE_11;
1559				NdisZeroMemory(pEntry, sizeof(struct rt_mac_table_entry));
1560				pEntry->PairwiseKey.KeyLen = 0;
1561				pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1562			}
1563			{
1564				{
1565					pEntry->ValidAsCLI = TRUE;
1566					pEntry->ValidAsWDS = FALSE;
1567					pEntry->ValidAsApCli = FALSE;
1568					pEntry->ValidAsMesh = FALSE;
1569					pEntry->ValidAsDls = FALSE;
1570				}
1571			}
1572
1573			pEntry->bIAmBadAtheros = FALSE;
1574			pEntry->pAd = pAd;
1575			pEntry->CMTimerRunning = FALSE;
1576			pEntry->EnqueueEapolStartTimerRunning =
1577			    EAPOL_START_DISABLE;
1578			pEntry->RSNIE_Len = 0;
1579			NdisZeroMemory(pEntry->R_Counter,
1580				       sizeof(pEntry->R_Counter));
1581			pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
1582
1583			if (pEntry->ValidAsMesh)
1584				pEntry->apidx =
1585				    (apidx - MIN_NET_DEVICE_FOR_MESH);
1586			else if (pEntry->ValidAsApCli)
1587				pEntry->apidx =
1588				    (apidx - MIN_NET_DEVICE_FOR_APCLI);
1589			else if (pEntry->ValidAsWDS)
1590				pEntry->apidx =
1591				    (apidx - MIN_NET_DEVICE_FOR_WDS);
1592			else
1593				pEntry->apidx = apidx;
1594
1595			{
1596				{
1597					pEntry->AuthMode = pAd->StaCfg.AuthMode;
1598					pEntry->WepStatus =
1599					    pAd->StaCfg.WepStatus;
1600					pEntry->PrivacyFilter =
1601					    Ndis802_11PrivFilterAcceptAll;
1602#ifdef RTMP_MAC_PCI
1603					AsicRemovePairwiseKeyEntry(pAd,
1604								   pEntry->
1605								   apidx,
1606								   (u8)i);
1607#endif /* RTMP_MAC_PCI // */
1608				}
1609			}
1610
1611			pEntry->GTKState = REKEY_NEGOTIATING;
1612			pEntry->PairwiseKey.KeyLen = 0;
1613			pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1614			pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
1615
1616			pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
1617			COPY_MAC_ADDR(pEntry->Addr, pAddr);
1618			pEntry->Sst = SST_NOT_AUTH;
1619			pEntry->AuthState = AS_NOT_AUTH;
1620			pEntry->Aid = (u16)i;	/*0; */
1621			pEntry->CapabilityInfo = 0;
1622			pEntry->PsMode = PWR_ACTIVE;
1623			pEntry->PsQIdleCount = 0;
1624			pEntry->NoDataIdleCount = 0;
1625			pEntry->AssocDeadLine = MAC_TABLE_ASSOC_TIMEOUT;
1626			pEntry->ContinueTxFailCnt = 0;
1627			InitializeQueueHeader(&pEntry->PsQueue);
1628
1629			pAd->MacTab.Size++;
1630			/* Add this entry into ASIC RX WCID search table */
1631			RTMP_STA_ENTRY_ADD(pAd, pEntry);
1632
1633			DBGPRINT(RT_DEBUG_TRACE,
1634				 ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",
1635				  i, pAd->MacTab.Size));
1636			break;
1637		}
1638	}
1639
1640	/* add this MAC entry into HASH table */
1641	if (pEntry) {
1642		HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1643		if (pAd->MacTab.Hash[HashIdx] == NULL) {
1644			pAd->MacTab.Hash[HashIdx] = pEntry;
1645		} else {
1646			pCurrEntry = pAd->MacTab.Hash[HashIdx];
1647			while (pCurrEntry->pNext != NULL)
1648				pCurrEntry = pCurrEntry->pNext;
1649			pCurrEntry->pNext = pEntry;
1650		}
1651	}
1652
1653	NdisReleaseSpinLock(&pAd->MacTabLock);
1654	return pEntry;
1655}
1656
1657/*
1658	==========================================================================
1659	Description:
1660		Delete a specified client from MAC table
1661	==========================================================================
1662 */
1663BOOLEAN MacTableDeleteEntry(struct rt_rtmp_adapter *pAd,
1664			    u16 wcid, u8 *pAddr)
1665{
1666	u16 HashIdx;
1667	struct rt_mac_table_entry *pEntry, *pPrevEntry, *pProbeEntry;
1668	BOOLEAN Cancelled;
1669	/*u16        offset; // unused variable */
1670	/*u8 j;                      // unused variable */
1671
1672	if (wcid >= MAX_LEN_OF_MAC_TABLE)
1673		return FALSE;
1674
1675	NdisAcquireSpinLock(&pAd->MacTabLock);
1676
1677	HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1678	/*pEntry = pAd->MacTab.Hash[HashIdx]; */
1679	pEntry = &pAd->MacTab.Content[wcid];
1680
1681	if (pEntry
1682	    && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS
1683		|| pEntry->ValidAsMesh)) {
1684		if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) {
1685
1686			/* Delete this entry from ASIC on-chip WCID Table */
1687			RTMP_STA_ENTRY_MAC_RESET(pAd, wcid);
1688
1689			/* free resources of BA */
1690			BASessionTearDownALL(pAd, pEntry->Aid);
1691
1692			pPrevEntry = NULL;
1693			pProbeEntry = pAd->MacTab.Hash[HashIdx];
1694			ASSERT(pProbeEntry);
1695
1696			/* update Hash list */
1697			do {
1698				if (pProbeEntry == pEntry) {
1699					if (pPrevEntry == NULL) {
1700						pAd->MacTab.Hash[HashIdx] =
1701						    pEntry->pNext;
1702					} else {
1703						pPrevEntry->pNext =
1704						    pEntry->pNext;
1705					}
1706					break;
1707				}
1708
1709				pPrevEntry = pProbeEntry;
1710				pProbeEntry = pProbeEntry->pNext;
1711			} while (pProbeEntry);
1712
1713			/* not found ! */
1714			ASSERT(pProbeEntry != NULL);
1715
1716			RTMP_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
1717
1718			if (pEntry->EnqueueEapolStartTimerRunning !=
1719			    EAPOL_START_DISABLE) {
1720				RTMPCancelTimer(&pEntry->
1721						EnqueueStartForPSKTimer,
1722						&Cancelled);
1723				pEntry->EnqueueEapolStartTimerRunning =
1724				    EAPOL_START_DISABLE;
1725			}
1726
1727			NdisZeroMemory(pEntry, sizeof(struct rt_mac_table_entry));
1728			pAd->MacTab.Size--;
1729			DBGPRINT(RT_DEBUG_TRACE,
1730				 ("MacTableDeleteEntry1 - Total= %d\n",
1731				  pAd->MacTab.Size));
1732		} else {
1733			DBGPRINT(RT_DEBUG_OFF,
1734				 ("\n%s: Impossible Wcid = %d !\n",
1735				  __func__, wcid));
1736		}
1737	}
1738
1739	NdisReleaseSpinLock(&pAd->MacTabLock);
1740
1741	/*Reset operating mode when no Sta. */
1742	if (pAd->MacTab.Size == 0) {
1743		pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
1744		RTMP_UPDATE_PROTECT(pAd);	/* edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet */
1745	}
1746
1747	return TRUE;
1748}
1749
1750/*
1751	==========================================================================
1752	Description:
1753		This routine reset the entire MAC table. All packets pending in
1754		the power-saving queues are freed here.
1755	==========================================================================
1756 */
1757void MacTableReset(struct rt_rtmp_adapter *pAd)
1758{
1759	int i;
1760
1761	DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
1762	/*NdisAcquireSpinLock(&pAd->MacTabLock); */
1763
1764	for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
1765#ifdef RTMP_MAC_PCI
1766		RTMP_STA_ENTRY_MAC_RESET(pAd, i);
1767#endif /* RTMP_MAC_PCI // */
1768		if (pAd->MacTab.Content[i].ValidAsCLI == TRUE) {
1769
1770			/* free resources of BA */
1771			BASessionTearDownALL(pAd, i);
1772
1773			pAd->MacTab.Content[i].ValidAsCLI = FALSE;
1774
1775#ifdef RTMP_MAC_USB
1776			NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6);
1777			RTMP_STA_ENTRY_MAC_RESET(pAd, i);
1778#endif /* RTMP_MAC_USB // */
1779
1780			/*AsicDelWcidTab(pAd, i); */
1781		}
1782	}
1783
1784	return;
1785}
1786
1787/*
1788	==========================================================================
1789	Description:
1790
1791	IRQL = DISPATCH_LEVEL
1792
1793	==========================================================================
1794*/
1795void AssocParmFill(struct rt_rtmp_adapter *pAd,
1796		   struct rt_mlme_assoc_req *AssocReq,
1797		   u8 *pAddr,
1798		   u16 CapabilityInfo,
1799		   unsigned long Timeout, u16 ListenIntv)
1800{
1801	COPY_MAC_ADDR(AssocReq->Addr, pAddr);
1802	/* Add mask to support 802.11b mode only */
1803	AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO;	/* not cf-pollable, not cf-poll-request */
1804	AssocReq->Timeout = Timeout;
1805	AssocReq->ListenIntv = ListenIntv;
1806}
1807
1808/*
1809	==========================================================================
1810	Description:
1811
1812	IRQL = DISPATCH_LEVEL
1813
1814	==========================================================================
1815*/
1816void DisassocParmFill(struct rt_rtmp_adapter *pAd,
1817		      struct rt_mlme_disassoc_req *DisassocReq,
1818		      u8 *pAddr, u16 Reason)
1819{
1820	COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
1821	DisassocReq->Reason = Reason;
1822}
1823
1824/*
1825	========================================================================
1826
1827	Routine Description:
1828		Check the out going frame, if this is an DHCP or ARP datagram
1829	will be duplicate another frame at low data rate transmit.
1830
1831	Arguments:
1832		pAd 		Pointer to our adapter
1833		pPacket 	Pointer to outgoing Ndis frame
1834
1835	Return Value:
1836		TRUE		To be duplicate at Low data rate transmit. (1mb)
1837		FALSE		Do nothing.
1838
1839	IRQL = DISPATCH_LEVEL
1840
1841	Note:
1842
1843		MAC header + IP Header + UDP Header
1844		  14 Bytes	  20 Bytes
1845
1846		UDP Header
1847		00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
1848						Source Port
1849		16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
1850					Destination Port
1851
1852		port 0x43 means Bootstrap Protocol, server.
1853		Port 0x44 means Bootstrap Protocol, client.
1854
1855	========================================================================
1856*/
1857
1858BOOLEAN RTMPCheckDHCPFrame(struct rt_rtmp_adapter *pAd, void *pPacket)
1859{
1860	struct rt_packet_info PacketInfo;
1861	unsigned long NumberOfBytesRead = 0;
1862	unsigned long CurrentOffset = 0;
1863	void *pVirtualAddress = NULL;
1864	u32 NdisBufferLength;
1865	u8 *pSrc;
1866	u16 Protocol;
1867	u8 ByteOffset36 = 0;
1868	u8 ByteOffset38 = 0;
1869	BOOLEAN ReadFirstParm = TRUE;
1870
1871	RTMP_QueryPacketInfo(pPacket, &PacketInfo, (u8 **) & pVirtualAddress,
1872			     &NdisBufferLength);
1873
1874	NumberOfBytesRead += NdisBufferLength;
1875	pSrc = (u8 *)pVirtualAddress;
1876	Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
1877
1878	/* */
1879	/* Check DHCP & BOOTP protocol */
1880	/* */
1881	while (NumberOfBytesRead <= PacketInfo.TotalPacketLength) {
1882		if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE)) {
1883			CurrentOffset =
1884			    35 - (NumberOfBytesRead - NdisBufferLength);
1885			ByteOffset36 = *(pSrc + CurrentOffset);
1886			ReadFirstParm = FALSE;
1887		}
1888
1889		if (NumberOfBytesRead >= 37) {
1890			CurrentOffset =
1891			    37 - (NumberOfBytesRead - NdisBufferLength);
1892			ByteOffset38 = *(pSrc + CurrentOffset);
1893			/*End of Read */
1894			break;
1895		}
1896		return FALSE;
1897	}
1898
1899	/* Check for DHCP & BOOTP protocol */
1900	if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43)) {
1901		/* */
1902		/* 2054 (hex 0806) for ARP datagrams */
1903		/* if this packet is not ARP datagrams, then do nothing */
1904		/* ARP datagrams will also be duplicate at 1mb broadcast frames */
1905		/* */
1906		if (Protocol != 0x0806)
1907			return FALSE;
1908	}
1909
1910	return TRUE;
1911}
1912
1913BOOLEAN RTMPCheckEtherType(struct rt_rtmp_adapter *pAd, void *pPacket)
1914{
1915	u16 TypeLen;
1916	u8 Byte0, Byte1;
1917	u8 *pSrcBuf;
1918	u32 pktLen;
1919	u16 srcPort, dstPort;
1920	BOOLEAN status = TRUE;
1921
1922	pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
1923	pktLen = GET_OS_PKT_LEN(pPacket);
1924
1925	ASSERT(pSrcBuf);
1926
1927	RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
1928
1929	/* get Ethernet protocol field */
1930	TypeLen = (pSrcBuf[12] << 8) | pSrcBuf[13];
1931
1932	pSrcBuf += LENGTH_802_3;	/* Skip the Ethernet Header. */
1933
1934	if (TypeLen <= 1500) {	/* 802.3, 802.3 LLC */
1935		/*
1936		   DestMAC(6) + SrcMAC(6) + Lenght(2) +
1937		   DSAP(1) + SSAP(1) + Control(1) +
1938		   if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
1939		   => + SNAP (5, OriginationID(3) + etherType(2))
1940		 */
1941		if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA
1942		    && pSrcBuf[2] == 0x03) {
1943			Sniff2BytesFromNdisBuffer((char *)pSrcBuf, 6,
1944						  &Byte0, &Byte1);
1945			RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
1946			TypeLen = (u16)((Byte0 << 8) + Byte1);
1947			pSrcBuf += 8;	/* Skip this LLC/SNAP header */
1948		} else {
1949			/*It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it. */
1950		}
1951	}
1952	/* If it's a VLAN packet, get the real Type/Length field. */
1953	if (TypeLen == 0x8100) {
1954		/* 0x8100 means VLAN packets */
1955
1956		/* Dest. MAC Address (6-bytes) +
1957		   Source MAC Address (6-bytes) +
1958		   Length/Type = 802.1Q Tag Type (2-byte) +
1959		   Tag Control Information (2-bytes) +
1960		   Length / Type (2-bytes) +
1961		   data payload (0-n bytes) +
1962		   Pad (0-p bytes) +
1963		   Frame Check Sequence (4-bytes) */
1964
1965		RTMP_SET_PACKET_VLAN(pPacket, 1);
1966		Sniff2BytesFromNdisBuffer((char *)pSrcBuf, 2, &Byte0,
1967					  &Byte1);
1968		TypeLen = (u16)((Byte0 << 8) + Byte1);
1969
1970		pSrcBuf += 4;	/* Skip the VLAN Header. */
1971	}
1972
1973	switch (TypeLen) {
1974	case 0x0800:
1975		{
1976			ASSERT((pktLen > 34));
1977			if (*(pSrcBuf + 9) == 0x11) {	/* udp packet */
1978				ASSERT((pktLen > 34));	/* 14 for ethernet header, 20 for IP header */
1979
1980				pSrcBuf += 20;	/* Skip the IP header */
1981				srcPort =
1982				    OS_NTOHS(get_unaligned
1983					     ((u16 *)(pSrcBuf)));
1984				dstPort =
1985				    OS_NTOHS(get_unaligned
1986					     ((u16 *)(pSrcBuf + 2)));
1987
1988				if ((srcPort == 0x44 && dstPort == 0x43) || (srcPort == 0x43 && dstPort == 0x44)) {	/*It's a BOOTP/DHCP packet */
1989					RTMP_SET_PACKET_DHCP(pPacket, 1);
1990				}
1991			}
1992		}
1993		break;
1994	case 0x0806:
1995		{
1996			/*ARP Packet. */
1997			RTMP_SET_PACKET_DHCP(pPacket, 1);
1998		}
1999		break;
2000	case 0x888e:
2001		{
2002			/* EAPOL Packet. */
2003			RTMP_SET_PACKET_EAPOL(pPacket, 1);
2004		}
2005		break;
2006	default:
2007		status = FALSE;
2008		break;
2009	}
2010
2011	return status;
2012
2013}
2014
2015void Update_Rssi_Sample(struct rt_rtmp_adapter *pAd,
2016			struct rt_rssi_sample *pRssi, struct rt_rxwi * pRxWI)
2017{
2018	char rssi0 = pRxWI->RSSI0;
2019	char rssi1 = pRxWI->RSSI1;
2020	char rssi2 = pRxWI->RSSI2;
2021
2022	if (rssi0 != 0) {
2023		pRssi->LastRssi0 = ConvertToRssi(pAd, (char)rssi0, RSSI_0);
2024		pRssi->AvgRssi0X8 =
2025		    (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
2026		pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
2027	}
2028
2029	if (rssi1 != 0) {
2030		pRssi->LastRssi1 = ConvertToRssi(pAd, (char)rssi1, RSSI_1);
2031		pRssi->AvgRssi1X8 =
2032		    (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
2033		pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
2034	}
2035
2036	if (rssi2 != 0) {
2037		pRssi->LastRssi2 = ConvertToRssi(pAd, (char)rssi2, RSSI_2);
2038		pRssi->AvgRssi2X8 =
2039		    (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
2040		pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
2041	}
2042}
2043
2044/* Normal legacy Rx packet indication */
2045void Indicate_Legacy_Packet(struct rt_rtmp_adapter *pAd,
2046			    struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
2047{
2048	void *pRxPacket = pRxBlk->pRxPacket;
2049	u8 Header802_3[LENGTH_802_3];
2050
2051	/* 1. get 802.3 Header */
2052	/* 2. remove LLC */
2053	/*              a. pointer pRxBlk->pData to payload */
2054	/*      b. modify pRxBlk->DataSize */
2055	RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2056
2057	if (pRxBlk->DataSize > MAX_RX_PKT_LEN) {
2058
2059		/* release packet */
2060		RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2061		return;
2062	}
2063
2064	STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
2065
2066#ifdef RTMP_MAC_USB
2067	if (pAd->CommonCfg.bDisableReordering == 0) {
2068		struct rt_ba_rec_entry *pBAEntry;
2069		unsigned long Now32;
2070		u8 Wcid = pRxBlk->pRxWI->WirelessCliID;
2071		u8 TID = pRxBlk->pRxWI->TID;
2072		u16 Idx;
2073
2074#define REORDERING_PACKET_TIMEOUT		((100 * OS_HZ)/1000)	/* system ticks -- 100 ms */
2075
2076		if (Wcid < MAX_LEN_OF_MAC_TABLE) {
2077			Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
2078			if (Idx != 0) {
2079				pBAEntry = &pAd->BATable.BARecEntry[Idx];
2080				/* update last rx time */
2081				NdisGetSystemUpTime(&Now32);
2082				if ((pBAEntry->list.qlen > 0) &&
2083				    RTMP_TIME_AFTER((unsigned long)Now32,
2084						    (unsigned long)(pBAEntry->
2085								    LastIndSeqAtTimer
2086								    +
2087								    (REORDERING_PACKET_TIMEOUT)))
2088				    ) {
2089					DBGPRINT(RT_DEBUG_OFF,
2090						 ("Indicate_Legacy_Packet():flush reordering_timeout_mpdus! RxWI->Flags=%d, pRxWI.TID=%d, RxD->AMPDU=%d!\n",
2091						  pRxBlk->Flags,
2092						  pRxBlk->pRxWI->TID,
2093						  pRxBlk->RxD.AMPDU));
2094					hex_dump("Dump the legacy Packet:",
2095						 GET_OS_PKT_DATAPTR(pRxBlk->
2096								    pRxPacket),
2097						 64);
2098					ba_flush_reordering_timeout_mpdus(pAd,
2099									  pBAEntry,
2100									  Now32);
2101				}
2102			}
2103		}
2104	}
2105#endif /* RTMP_MAC_USB // */
2106
2107	wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2108
2109	/* */
2110	/* pass this 802.3 packet to upper layer or forward this packet to WM directly */
2111	/* */
2112	ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
2113}
2114
2115/* Normal, AMPDU or AMSDU */
2116void CmmRxnonRalinkFrameIndicate(struct rt_rtmp_adapter *pAd,
2117				 struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
2118{
2119	if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU)
2120	    && (pAd->CommonCfg.bDisableReordering == 0)) {
2121		Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2122	} else {
2123		if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) {
2124			/* handle A-MSDU */
2125			Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2126		} else {
2127			Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
2128		}
2129	}
2130}
2131
2132void CmmRxRalinkFrameIndicate(struct rt_rtmp_adapter *pAd,
2133			      struct rt_mac_table_entry *pEntry,
2134			      struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
2135{
2136	u8 Header802_3[LENGTH_802_3];
2137	u16 Msdu2Size;
2138	u16 Payload1Size, Payload2Size;
2139	u8 *pData2;
2140	void *pPacket2 = NULL;
2141
2142	Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData + 1) << 8);
2143
2144	if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize)) {
2145		/* skip two byte MSDU2 len */
2146		pRxBlk->pData += 2;
2147		pRxBlk->DataSize -= 2;
2148	} else {
2149		/* release packet */
2150		RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
2151				    NDIS_STATUS_FAILURE);
2152		return;
2153	}
2154
2155	/* get 802.3 Header and  remove LLC */
2156	RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2157
2158	ASSERT(pRxBlk->pRxPacket);
2159
2160	/* Ralink Aggregation frame */
2161	pAd->RalinkCounters.OneSecRxAggregationCount++;
2162	Payload1Size = pRxBlk->DataSize - Msdu2Size;
2163	Payload2Size = Msdu2Size - LENGTH_802_3;
2164
2165	pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
2166
2167	pPacket2 =
2168	    duplicate_pkt(pAd, (pData2 - LENGTH_802_3), LENGTH_802_3, pData2,
2169			  Payload2Size, FromWhichBSSID);
2170
2171	if (!pPacket2) {
2172		/* release packet */
2173		RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
2174				    NDIS_STATUS_FAILURE);
2175		return;
2176	}
2177	/* update payload size of 1st packet */
2178	pRxBlk->DataSize = Payload1Size;
2179	wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2180
2181	ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket,
2182					 FromWhichBSSID);
2183
2184	if (pPacket2) {
2185		ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
2186	}
2187}
2188
2189#define RESET_FRAGFRAME(_fragFrame) \
2190	{								\
2191		_fragFrame.RxSize = 0;		\
2192		_fragFrame.Sequence = 0;	\
2193		_fragFrame.LastFrag = 0;	\
2194		_fragFrame.Flags = 0;		\
2195	}
2196
2197void *RTMPDeFragmentDataFrame(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk)
2198{
2199	struct rt_header_802_11 * pHeader = pRxBlk->pHeader;
2200	void *pRxPacket = pRxBlk->pRxPacket;
2201	u8 *pData = pRxBlk->pData;
2202	u16 DataSize = pRxBlk->DataSize;
2203	void *pRetPacket = NULL;
2204	u8 *pFragBuffer = NULL;
2205	BOOLEAN bReassDone = FALSE;
2206	u8 HeaderRoom = 0;
2207
2208	ASSERT(pHeader);
2209
2210	HeaderRoom = pData - (u8 *) pHeader;
2211
2212	/* Re-assemble the fragmented packets */
2213	if (pHeader->Frag == 0)	/* Frag. Number is 0 : First frag or only one pkt */
2214	{
2215		/* the first pkt of fragment, record it. */
2216		if (pHeader->FC.MoreFrag) {
2217			ASSERT(pAd->FragFrame.pFragPacket);
2218			pFragBuffer =
2219			    GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2220			pAd->FragFrame.RxSize = DataSize + HeaderRoom;
2221			NdisMoveMemory(pFragBuffer, pHeader,
2222				       pAd->FragFrame.RxSize);
2223			pAd->FragFrame.Sequence = pHeader->Sequence;
2224			pAd->FragFrame.LastFrag = pHeader->Frag;	/* Should be 0 */
2225			ASSERT(pAd->FragFrame.LastFrag == 0);
2226			goto done;	/* end of processing this frame */
2227		}
2228	} else			/*Middle & End of fragment */
2229	{
2230		if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
2231		    (pHeader->Frag != (pAd->FragFrame.LastFrag + 1))) {
2232			/* Fragment is not the same sequence or out of fragment number order */
2233			/* Reset Fragment control blk */
2234			RESET_FRAGFRAME(pAd->FragFrame);
2235			DBGPRINT(RT_DEBUG_ERROR,
2236				 ("Fragment is not the same sequence or out of fragment number order.\n"));
2237			goto done;	/* give up this frame */
2238		} else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE) {
2239			/* Fragment frame is too large, it exeeds the maximum frame size. */
2240			/* Reset Fragment control blk */
2241			RESET_FRAGFRAME(pAd->FragFrame);
2242			DBGPRINT(RT_DEBUG_ERROR,
2243				 ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
2244			goto done;	/* give up this frame */
2245		}
2246		/* */
2247		/* Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment. */
2248		/* In this case, we will dropt it. */
2249		/* */
2250		if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H))) {
2251			DBGPRINT(RT_DEBUG_ERROR,
2252				 ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n",
2253				  pHeader->Sequence, pHeader->Frag));
2254			goto done;	/* give up this frame */
2255		}
2256
2257		pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2258
2259		/* concatenate this fragment into the re-assembly buffer */
2260		NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData,
2261			       DataSize);
2262		pAd->FragFrame.RxSize += DataSize;
2263		pAd->FragFrame.LastFrag = pHeader->Frag;	/* Update fragment number */
2264
2265		/* Last fragment */
2266		if (pHeader->FC.MoreFrag == FALSE) {
2267			bReassDone = TRUE;
2268		}
2269	}
2270
2271done:
2272	/* always release rx fragmented packet */
2273	RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2274
2275	/* return defragmented packet if packet is reassembled completely */
2276	/* otherwise return NULL */
2277	if (bReassDone) {
2278		void *pNewFragPacket;
2279
2280		/* allocate a new packet buffer for fragment */
2281		pNewFragPacket =
2282		    RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
2283		if (pNewFragPacket) {
2284			/* update RxBlk */
2285			pRetPacket = pAd->FragFrame.pFragPacket;
2286			pAd->FragFrame.pFragPacket = pNewFragPacket;
2287			pRxBlk->pHeader =
2288			    (struct rt_header_802_11 *) GET_OS_PKT_DATAPTR(pRetPacket);
2289			pRxBlk->pData = (u8 *) pRxBlk->pHeader + HeaderRoom;
2290			pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
2291			pRxBlk->pRxPacket = pRetPacket;
2292		} else {
2293			RESET_FRAGFRAME(pAd->FragFrame);
2294		}
2295	}
2296
2297	return pRetPacket;
2298}
2299
2300void Indicate_AMSDU_Packet(struct rt_rtmp_adapter *pAd,
2301			   struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
2302{
2303	u32 nMSDU;
2304
2305	update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
2306	RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
2307	nMSDU =
2308	    deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData,
2309				       pRxBlk->DataSize);
2310}
2311
2312void Indicate_EAPOL_Packet(struct rt_rtmp_adapter *pAd,
2313			   struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
2314{
2315	struct rt_mac_table_entry *pEntry = NULL;
2316
2317	{
2318		pEntry = &pAd->MacTab.Content[BSSID_WCID];
2319		STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
2320		return;
2321	}
2322
2323	if (pEntry == NULL) {
2324		DBGPRINT(RT_DEBUG_WARN,
2325			 ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
2326		/* release packet */
2327		RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
2328				    NDIS_STATUS_FAILURE);
2329		return;
2330	}
2331}
2332
2333#define BCN_TBTT_OFFSET		64	/*defer 64 us */
2334void ReSyncBeaconTime(struct rt_rtmp_adapter *pAd)
2335{
2336
2337	u32 Offset;
2338
2339	Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
2340
2341	pAd->TbttTickCount++;
2342
2343	/* */
2344	/* The updated BeaconInterval Value will affect Beacon Interval after two TBTT */
2345	/* beacasue the original BeaconInterval had been loaded into next TBTT_TIMER */
2346	/* */
2347	if (Offset == (BCN_TBTT_OFFSET - 2)) {
2348		BCN_TIME_CFG_STRUC csr;
2349		RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2350		csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1;	/* ASIC register in units of 1/16 TU = 64us */
2351		RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2352	} else {
2353		if (Offset == (BCN_TBTT_OFFSET - 1)) {
2354			BCN_TIME_CFG_STRUC csr;
2355
2356			RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2357			csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4;	/* ASIC register in units of 1/16 TU */
2358			RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2359		}
2360	}
2361}
2362