• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
30 #define MAX_TX_IN_TBTT		(16)
31 
32 
33 UCHAR	SNAP_802_1H[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
34 UCHAR	SNAP_BRIDGE_TUNNEL[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8};
35 // Add Cisco Aironet SNAP heade for CCX2 support
36 UCHAR	SNAP_AIRONET[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00};
37 UCHAR	CKIP_LLC_SNAP[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02};
38 UCHAR	EAPOL_LLC_SNAP[]= {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e};
39 UCHAR	EAPOL[] = {0x88, 0x8e};
40 UCHAR   TPID[] = {0x81, 0x00}; /* VLAN related */
41 
42 UCHAR	IPX[] = {0x81, 0x37};
43 UCHAR	APPLE_TALK[] = {0x80, 0xf3};
44 UCHAR	RateIdToPlcpSignal[12] = {
45 	 0, /* RATE_1 */	1, /* RATE_2 */ 	2, /* RATE_5_5 */	3, /* RATE_11 */	// see BBP spec
46 	11, /* RATE_6 */   15, /* RATE_9 */    10, /* RATE_12 */   14, /* RATE_18 */	// see IEEE802.11a-1999 p.14
47 	 9, /* RATE_24 */  13, /* RATE_36 */	8, /* RATE_48 */   12  /* RATE_54 */ }; // see IEEE802.11a-1999 p.14
48 
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
54 };
55 
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
60 };
61 UCHAR	 RxwiMCSToOfdmRate[12] = {
62 	RATE_6,  RATE_9,	RATE_12,  RATE_18,
63 	RATE_24,  RATE_36,	RATE_48,  RATE_54,	// OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3
64 	4,  5,	6,  7,	// OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7
65 };
66 
67 char*   MCSToMbps[] = {"1Mbps","2Mbps","5.5Mbps","11Mbps","06Mbps","09Mbps","12Mbps","18Mbps","24Mbps","36Mbps","48Mbps","54Mbps","MM-0","MM-1","MM-2","MM-3","MM-4","MM-5","MM-6","MM-7","MM-8","MM-9","MM-10","MM-11","MM-12","MM-13","MM-14","MM-15","MM-32","ee1","ee2","ee3"};
68 
69 UCHAR default_cwmin[]={CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1, CW_MIN_IN_BITS-2};
70 //UCHAR default_cwmax[]={CW_MAX_IN_BITS, CW_MAX_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1};
71 UCHAR default_sta_aifsn[]={3,7,2,2};
72 
73 UCHAR MapUserPriorityToAccessCategory[8] = {QID_AC_BE, QID_AC_BK, QID_AC_BK, QID_AC_BE, QID_AC_VI, QID_AC_VI, QID_AC_VO, QID_AC_VO};
74 
75 
76 /*
77 	========================================================================
78 
79 	Routine Description:
80 		API for MLME to transmit management frame to AP (BSS Mode)
81 	or station (IBSS Mode)
82 
83 	Arguments:
84 		pAd Pointer to our adapter
85 		pData		Pointer to the outgoing 802.11 frame
86 		Length		Size of outgoing management frame
87 
88 	Return Value:
89 		NDIS_STATUS_FAILURE
90 		NDIS_STATUS_PENDING
91 		NDIS_STATUS_SUCCESS
92 
93 	IRQL = PASSIVE_LEVEL
94 	IRQL = DISPATCH_LEVEL
95 
96 	Note:
97 
98 	========================================================================
99 */
MiniportMMRequest(IN PRTMP_ADAPTER pAd,IN UCHAR QueIdx,IN PUCHAR pData,IN UINT Length)100 NDIS_STATUS MiniportMMRequest(
101 	IN	PRTMP_ADAPTER	pAd,
102 	IN	UCHAR			QueIdx,
103 	IN	PUCHAR			pData,
104 	IN	UINT			Length)
105 {
106 	PNDIS_PACKET	pPacket;
107 	NDIS_STATUS  	Status = NDIS_STATUS_SUCCESS;
108 	ULONG	 		FreeNum;
109 	UCHAR			IrqState;
110 	UCHAR			rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN];
111 
112 	ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
113 
114 	QueIdx=3;
115 
116 	// 2860C use Tx Ring
117 
118 	IrqState = pAd->irq_disabled;
119 
120 	do
121 	{
122 		// Reset is in progress, stop immediately
123 		if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
124 			 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)||
125 			 !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
126 		{
127 			Status = NDIS_STATUS_FAILURE;
128 			break;
129 		}
130 
131 		// Check Free priority queue
132 		// Since we use PBF Queue2 for management frame.  Its corresponding DMA ring should be using TxRing.
133 
134 		// 2860C use Tx Ring
135 		if (pAd->MACVersion == 0x28600100)
136 		{
137 			FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
138 		}
139 		else
140 		{
141 			FreeNum = GET_MGMTRING_FREENO(pAd);
142 		}
143 
144 		if ((FreeNum > 0))
145 		{
146 			// We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870
147 			NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE));
148 			Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE), pData, Length);
149 			if (Status != NDIS_STATUS_SUCCESS)
150 			{
151 				DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
152 				break;
153 			}
154 
155 			//pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
156 			//pAd->CommonCfg.MlmeRate = RATE_2;
157 
158 
159 			Status = MlmeHardTransmit(pAd, QueIdx, pPacket);
160 			if (Status != NDIS_STATUS_SUCCESS)
161 				RTMPFreeNdisPacket(pAd, pPacket);
162 		}
163 		else
164 		{
165 			pAd->RalinkCounters.MgmtRingFullCount++;
166 			DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n",
167 										QueIdx, pAd->RalinkCounters.MgmtRingFullCount));
168 		}
169 
170 	} while (FALSE);
171 
172 
173 	return Status;
174 }
175 
176 
177 
178 
179 /*
180 	========================================================================
181 
182 	Routine Description:
183 		Copy frame from waiting queue into relative ring buffer and set
184 	appropriate ASIC register to kick hardware transmit function
185 
186 	Arguments:
187 		pAd Pointer to our adapter
188 		pBuffer 	Pointer to	memory of outgoing frame
189 		Length		Size of outgoing management frame
190 
191 	Return Value:
192 		NDIS_STATUS_FAILURE
193 		NDIS_STATUS_PENDING
194 		NDIS_STATUS_SUCCESS
195 
196 	IRQL = PASSIVE_LEVEL
197 	IRQL = DISPATCH_LEVEL
198 
199 	Note:
200 
201 	========================================================================
202 */
MlmeHardTransmit(IN PRTMP_ADAPTER pAd,IN UCHAR QueIdx,IN PNDIS_PACKET pPacket)203 NDIS_STATUS MlmeHardTransmit(
204 	IN	PRTMP_ADAPTER	pAd,
205 	IN	UCHAR			QueIdx,
206 	IN	PNDIS_PACKET	pPacket)
207 {
208 	if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
209 #ifdef CARRIER_DETECTION_SUPPORT
210 #endif // CARRIER_DETECTION_SUPPORT //
211 		)
212 	{
213 		return NDIS_STATUS_FAILURE;
214 	}
215 
216 		return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
217 
218 }
219 
220 
221 
MlmeHardTransmitMgmtRing(IN PRTMP_ADAPTER pAd,IN UCHAR QueIdx,IN PNDIS_PACKET pPacket)222 NDIS_STATUS MlmeHardTransmitMgmtRing(
223 	IN	PRTMP_ADAPTER	pAd,
224 	IN	UCHAR	QueIdx,
225 	IN	PNDIS_PACKET	pPacket)
226 {
227 	PACKET_INFO 	PacketInfo;
228 	PUCHAR			pSrcBufVA;
229 	UINT			SrcBufLen;
230 	PHEADER_802_11	pHeader_802_11;
231 	BOOLEAN 		bAckRequired, bInsertTimestamp;
232 	UCHAR			MlmeRate;
233 	PTXWI_STRUC 	pFirstTxWI;
234 	MAC_TABLE_ENTRY	*pMacEntry = NULL;
235 
236 	RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
237 
238 	// Make sure MGMT ring resource won't be used by other threads
239 // sample, for IRQ LOCK -> SEM LOCK
240 //	IrqState = pAd->irq_disabled;
241 //	if (!IrqState)
242 		RTMP_SEM_LOCK(&pAd->MgmtRingLock);
243 
244 
245 	if (pSrcBufVA == NULL)
246 	{
247 		// The buffer shouldn't be NULL
248 //		if (!IrqState)
249 			RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
250 		return NDIS_STATUS_FAILURE;
251 	}
252 
253 #ifdef CONFIG_STA_SUPPORT
254 	IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
255 	{
256 		// outgoing frame always wakeup PHY to prevent frame lost
257 		if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
258 			AsicForceWakeup(pAd, TRUE);
259 	}
260 #endif // CONFIG_STA_SUPPORT //
261 
262 	pFirstTxWI = (PTXWI_STRUC)(pSrcBufVA +  TXINFO_SIZE);
263 	pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); //TXWI_SIZE);
264 
265 	if (pHeader_802_11->Addr1[0] & 0x01)
266 	{
267 		MlmeRate = pAd->CommonCfg.BasicMlmeRate;
268 	}
269 	else
270 	{
271 		MlmeRate = pAd->CommonCfg.MlmeRate;
272 	}
273 
274 	// Verify Mlme rate for a / g bands.
275 	if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
276 		MlmeRate = RATE_6;
277 
278 	if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
279 		(pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
280 	{
281 		pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
282 	}
283 
284 #ifdef CONFIG_STA_SUPPORT
285 	IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
286 	{
287 		// Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode.
288 		if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED
289 #ifdef DOT11_N_SUPPORT
290 			|| pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED
291 #endif // DOT11_N_SUPPORT //
292 		)
293 		{
294 			if (pAd->LatchRfRegs.Channel > 14)
295 				pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
296 			else
297 				pAd->CommonCfg.MlmeTransmit.field.MODE = 0;
298 		}
299 	}
300 #endif // CONFIG_STA_SUPPORT //
301 
302 	//
303 	// Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
304 	// Snice it's been set to 0 while on MgtMacHeaderInit
305 	// By the way this will cause frame to be send on PWR_SAVE failed.
306 	//
307 	// pHeader_802_11->FC.PwrMgmt = 0; // (pAd->StaCfg.Psm == PWR_SAVE);
308 	//
309 	// In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
310 #ifdef CONFIG_STA_SUPPORT
311     // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
312 	if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL))
313 	{
314 		if ((pAd->StaCfg.Psm == PWR_SAVE) &&
315 			(pHeader_802_11->FC.SubType == SUBTYPE_ACTION))
316 			pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
317 		else
318 			pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
319 	}
320 #endif // CONFIG_STA_SUPPORT //
321 
322 	bInsertTimestamp = FALSE;
323 	if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
324 	{
325 #ifdef CONFIG_STA_SUPPORT
326 		//Set PM bit in ps-poll, to fix WLK 1.2  PowerSaveMode_ext failure issue.
327 		if ((pAd->OpMode == OPMODE_STA) && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL))
328 		{
329 			pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
330 		}
331 #endif // CONFIG_STA_SUPPORT //
332 		bAckRequired = FALSE;
333 	}
334 	else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
335 	{
336 		//pAd->Sequence++;
337 		//pHeader_802_11->Sequence = pAd->Sequence;
338 
339 		if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
340 		{
341 			bAckRequired = FALSE;
342 			pHeader_802_11->Duration = 0;
343 		}
344 		else
345 		{
346 			bAckRequired = TRUE;
347 			pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
348 			if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
349 			{
350 				bInsertTimestamp = TRUE;
351 			}
352 		}
353 	}
354 
355 	pHeader_802_11->Sequence = pAd->Sequence++;
356 	if (pAd->Sequence >0xfff)
357 		pAd->Sequence = 0;
358 
359 	// Before radar detection done, mgmt frame can not be sent but probe req
360 	// Because we need to use probe req to trigger driver to send probe req in passive scan
361 	if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
362 		&& (pAd->CommonCfg.bIEEE80211H == 1)
363 		&& (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
364 	{
365 		DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
366 //		if (!IrqState)
367 			RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
368 		return (NDIS_STATUS_FAILURE);
369 	}
370 
371 #ifdef RT_BIG_ENDIAN
372 	RTMPFrameEndianChange(pAd, (PUCHAR)pHeader_802_11, DIR_WRITE, FALSE);
373 #endif
374 
375 	//
376 	// fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
377 	// should always has only one ohysical buffer, and the whole frame size equals
378 	// to the first scatter buffer size
379 	//
380 
381 	// Initialize TX Descriptor
382 	// For inter-frame gap, the number is for this frame and next frame
383 	// For MLME rate, we will fix as 2Mb to match other vendor's implement
384 //	pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
385 
386 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
387 	if (pMacEntry == NULL)
388 	{
389 		RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
390 		0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID_MGMT, 0,  (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
391 	}
392 	else
393 	{
394 		RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
395 					bInsertTimestamp, FALSE, bAckRequired, FALSE,
396 					0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE),
397 					pMacEntry->MaxHTPhyMode.field.MCS, 0,
398 					(UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
399 					IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
400 	}
401 
402 #ifdef RT_BIG_ENDIAN
403 	RTMPWIEndianChange((PUCHAR)pFirstTxWI, TYPE_TXWI);
404 #endif
405 
406 	// Now do hardware-depened kick out.
407 	HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen);
408 
409 	// Make sure to release MGMT ring resource
410 //	if (!IrqState)
411 		RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
412 	return NDIS_STATUS_SUCCESS;
413 }
414 
415 
416 /********************************************************************************
417 
418 	New DeQueue Procedures.
419 
420  ********************************************************************************/
421 
422 #define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) 				\
423 			do{													\
424 				if (bIntContext == FALSE)						\
425 				RTMP_IRQ_LOCK((lock), IrqFlags);		\
426 			}while(0)
427 
428 #define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags)				\
429 			do{													\
430 				if (bIntContext == FALSE)						\
431 					RTMP_IRQ_UNLOCK((lock), IrqFlags);	\
432 			}while(0)
433 
434 
435 #if 0
436 static VOID dumpTxBlk(TX_BLK *pTxBlk)
437 {
438 	NDIS_PACKET *pPacket;
439 	int i, frameNum;
440 	PQUEUE_ENTRY	pQEntry;
441 
442 	printk("Dump TX_BLK Structure:\n");
443 	printk("\tTxFrameType=%d!\n", pTxBlk->TxFrameType);
444 	printk("\tTotalFrameLen=%d\n", pTxBlk->TotalFrameLen);
445 	printk("\tTotalFrameNum=%ld!\n", pTxBlk->TxPacketList.Number);
446 	printk("\tTotalFragNum=%d!\n", pTxBlk->TotalFragNum);
447 	printk("\tpPacketList=\n");
448 
449 	frameNum = pTxBlk->TxPacketList.Number;
450 
451 	for(i=0; i < frameNum; i++)
452 	{	int j;
453 		UCHAR	*pBuf;
454 
455 		pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
456 		pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
457 		if (pPacket)
458 		{
459 			pBuf = GET_OS_PKT_DATAPTR(pPacket);
460 			printk("\t\t[%d]:ptr=0x%x, Len=%d!\n", i, (UINT32)(GET_OS_PKT_DATAPTR(pPacket)), GET_OS_PKT_LEN(pPacket));
461 			printk("\t\t");
462 			for (j =0 ; j < GET_OS_PKT_LEN(pPacket); j++)
463 			{
464 				printk("%02x ", (pBuf[j] & 0xff));
465 				if (j == 16)
466 					break;
467 			}
468 			InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
469 		}
470 	}
471 	printk("\tWcid=%d!\n", pTxBlk->Wcid);
472 	printk("\tapidx=%d!\n", pTxBlk->apidx);
473 	printk("----EndOfDump\n");
474 
475 }
476 #endif
477 
478 
479 /*
480 	========================================================================
481 	Tx Path design algorithm:
482 		Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal),
483 		Specific Packet Type. Following show the classification rule and policy for each kinds of packets.
484 				Classification Rule=>
485 					Multicast: (*addr1 & 0x01) == 0x01
486 					Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc.
487 					11N Rate : If peer support HT
488 								(1).AMPDU  -- If TXBA is negotiated.
489 								(2).AMSDU  -- If AMSDU is capable for both peer and ourself.
490 											*). AMSDU can embedded in a AMPDU, but now we didn't support it.
491 								(3).Normal -- Other packets which send as 11n rate.
492 
493 					B/G Rate : If peer is b/g only.
494 								(1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6
495 								(2).Normal -- Other packets which send as b/g rate.
496 					Fragment:
497 								The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
498 
499 				Classified Packet Handle Rule=>
500 					Multicast:
501 								No ACK, 		//pTxBlk->bAckRequired = FALSE;
502 								No WMM, 		//pTxBlk->bWMM = FALSE;
503 								No piggyback,   //pTxBlk->bPiggyBack = FALSE;
504 								Force LowRate,  //pTxBlk->bForceLowRate = TRUE;
505 					Specific :	Basically, for specific packet, we should handle it specifically, but now all specific packets are use
506 									the same policy to handle it.
507 								Force LowRate,  //pTxBlk->bForceLowRate = TRUE;
508 
509 					11N Rate :
510 								No piggyback,	//pTxBlk->bPiggyBack = FALSE;
511 
512 								(1).AMSDU
513 									pTxBlk->bWMM = TRUE;
514 								(2).AMPDU
515 									pTxBlk->bWMM = TRUE;
516 								(3).Normal
517 
518 					B/G Rate :
519 								(1).ARALINK
520 
521 								(2).Normal
522 	========================================================================
523 */
TxPktClassification(IN RTMP_ADAPTER * pAd,IN PNDIS_PACKET pPacket)524 static UCHAR TxPktClassification(
525 	IN RTMP_ADAPTER *pAd,
526 	IN PNDIS_PACKET  pPacket)
527 {
528 	UCHAR			TxFrameType = TX_UNKOWN_FRAME;
529 	UCHAR			Wcid;
530 	MAC_TABLE_ENTRY	*pMacEntry = NULL;
531 #ifdef DOT11_N_SUPPORT
532 	BOOLEAN			bHTRate = FALSE;
533 #endif // DOT11_N_SUPPORT //
534 
535 	Wcid = RTMP_GET_PACKET_WCID(pPacket);
536 	if (Wcid == MCAST_WCID)
537 	{	// Handle for RA is Broadcast/Multicast Address.
538 		return TX_MCAST_FRAME;
539 	}
540 
541 	// Handle for unicast packets
542 	pMacEntry = &pAd->MacTab.Content[Wcid];
543 	if (RTMP_GET_PACKET_LOWRATE(pPacket))
544 	{	// It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame
545 		TxFrameType = TX_LEGACY_FRAME;
546 	}
547 #ifdef DOT11_N_SUPPORT
548 	else if (IS_HT_RATE(pMacEntry))
549 	{	// it's a 11n capable packet
550 
551 		// Depends on HTPhyMode to check if the peer support the HTRate transmission.
552 		// 	Currently didn't support A-MSDU embedded in A-MPDU
553 		bHTRate = TRUE;
554 		if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE))
555 			TxFrameType = TX_LEGACY_FRAME;
556 #ifdef UAPSD_AP_SUPPORT
557 		else if (RTMP_GET_PACKET_EOSP(pPacket))
558 			TxFrameType = TX_LEGACY_FRAME;
559 #endif // UAPSD_AP_SUPPORT //
560 		else if((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0)
561 			return TX_AMPDU_FRAME;
562 		else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED))
563 			return TX_AMSDU_FRAME;
564 		else
565 			TxFrameType = TX_LEGACY_FRAME;
566 	}
567 #endif // DOT11_N_SUPPORT //
568 	else
569 	{	// it's a legacy b/g packet.
570 		if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) &&
571 			(RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) &&
572 			(!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
573 		{	// if peer support Ralink Aggregation, we use it.
574 			TxFrameType = TX_RALINK_FRAME;
575 		}
576 		else
577 		{
578 			TxFrameType = TX_LEGACY_FRAME;
579 		}
580 	}
581 
582 	// Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU.
583 	if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) && (TxFrameType == TX_LEGACY_FRAME))
584 		TxFrameType = TX_FRAG_FRAME;
585 
586 	return TxFrameType;
587 }
588 
589 
RTMP_FillTxBlkInfo(IN RTMP_ADAPTER * pAd,IN TX_BLK * pTxBlk)590 BOOLEAN RTMP_FillTxBlkInfo(
591 	IN RTMP_ADAPTER *pAd,
592 	IN TX_BLK *pTxBlk)
593 {
594 	PACKET_INFO			PacketInfo;
595 	PNDIS_PACKET		pPacket;
596 	PMAC_TABLE_ENTRY	pMacEntry = NULL;
597 
598 	pPacket = pTxBlk->pPacket;
599 	RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
600 
601 	pTxBlk->Wcid	 	 		= RTMP_GET_PACKET_WCID(pPacket);
602 	pTxBlk->apidx		 		= RTMP_GET_PACKET_IF(pPacket);
603 	pTxBlk->UserPriority 		= RTMP_GET_PACKET_UP(pPacket);
604 	pTxBlk->FrameGap = IFS_HTTXOP;		// ASIC determine Frame Gap
605 
606 	if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket))
607 		TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame);
608 	else
609 		TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame);
610 
611 	// Default to clear this flag
612 	TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS);
613 
614 
615 	if (pTxBlk->Wcid == MCAST_WCID)
616 	{
617 		pTxBlk->pMacEntry = NULL;
618 		{
619 #ifdef MCAST_RATE_SPECIFIC
620 			PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket);
621 			if (((*pDA & 0x01) == 0x01) && (*pDA != 0xff))
622 				pTxBlk->pTransmit = &pAd->CommonCfg.MCastPhyMode;
623 			else
624 #endif // MCAST_RATE_SPECIFIC //
625 				pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
626 		}
627 
628 		TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);	// AckRequired = FALSE, when broadcast packet in Adhoc mode.
629 		//TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate);
630 		TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag);
631 		TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
632 		if (RTMP_GET_PACKET_MOREDATA(pPacket))
633 		{
634 			TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
635 		}
636 
637 	}
638 	else
639 	{
640 		pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
641 		pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode;
642 
643 		pMacEntry = pTxBlk->pMacEntry;
644 
645 
646 		// For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK.
647 		if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK)
648 			TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
649 		else
650 			TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired);
651 
652 		{
653 
654 #ifdef CONFIG_STA_SUPPORT
655 			IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
656 			{
657 
658 				// If support WMM, enable it.
659 				if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
660 					CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))
661 					TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM);
662 			}
663 #endif // CONFIG_STA_SUPPORT //
664 		}
665 
666 		if (pTxBlk->TxFrameType == TX_LEGACY_FRAME)
667 		{
668 			if ( (RTMP_GET_PACKET_LOWRATE(pPacket)) ||
669                 ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1)))
670 			{	// Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate.
671 				pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
672 #ifdef DOT11_N_SUPPORT
673 				// Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it???
674 				if (IS_HT_STA(pTxBlk->pMacEntry) &&
675 					(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) &&
676 					((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)))
677 				{
678 					TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
679 					TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS);
680 				}
681 #endif // DOT11_N_SUPPORT //
682 			}
683 
684 #ifdef DOT11_N_SUPPORT
685 			if ( (IS_HT_RATE(pMacEntry) == FALSE) &&
686 				(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE)))
687 			{	// Currently piggy-back only support when peer is operate in b/g mode.
688 				TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack);
689 			}
690 #endif // DOT11_N_SUPPORT //
691 
692 			if (RTMP_GET_PACKET_MOREDATA(pPacket))
693 			{
694 				TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
695 			}
696 #ifdef UAPSD_AP_SUPPORT
697 			if (RTMP_GET_PACKET_EOSP(pPacket))
698 			{
699 				TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP);
700 			}
701 #endif // UAPSD_AP_SUPPORT //
702 		}
703 		else if (pTxBlk->TxFrameType == TX_FRAG_FRAME)
704 		{
705 			TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag);
706 		}
707 
708 		pMacEntry->DebugTxCount++;
709 	}
710 
711 	return TRUE;
712 
713 FillTxBlkErr:
714 	return FALSE;
715 }
716 
717 
CanDoAggregateTransmit(IN RTMP_ADAPTER * pAd,IN NDIS_PACKET * pPacket,IN TX_BLK * pTxBlk)718 BOOLEAN CanDoAggregateTransmit(
719 	IN RTMP_ADAPTER *pAd,
720 	IN NDIS_PACKET *pPacket,
721 	IN TX_BLK		*pTxBlk)
722 {
723 
724 	//printk("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType);
725 
726 	if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
727 		return FALSE;
728 
729 	if (RTMP_GET_PACKET_DHCP(pPacket) ||
730 		RTMP_GET_PACKET_EAPOL(pPacket) ||
731 		RTMP_GET_PACKET_WAI(pPacket))
732 		return FALSE;
733 
734 	if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) &&
735 		((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100)))
736 	{	// For AMSDU, allow the packets with total length < max-amsdu size
737 		return FALSE;
738 	}
739 
740 	if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) &&
741 		(pTxBlk->TxPacketList.Number == 2))
742 	{	// For RALINK-Aggregation, allow two frames in one batch.
743 		return FALSE;
744 	}
745 
746 #ifdef CONFIG_STA_SUPPORT
747 	if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP
748 		return TRUE;
749 	else
750 #endif // CONFIG_STA_SUPPORT //
751 		return FALSE;
752 
753 }
754 
755 
756 /*
757 	========================================================================
758 
759 	Routine Description:
760 		To do the enqueue operation and extract the first item of waiting
761 		list. If a number of available shared memory segments could meet
762 		the request of extracted item, the extracted item will be fragmented
763 		into shared memory segments.
764 
765 	Arguments:
766 		pAd Pointer to our adapter
767 		pQueue		Pointer to Waiting Queue
768 
769 	Return Value:
770 		None
771 
772 	IRQL = DISPATCH_LEVEL
773 
774 	Note:
775 
776 	========================================================================
777 */
RTMPDeQueuePacket(IN PRTMP_ADAPTER pAd,IN BOOLEAN bIntContext,IN UCHAR QIdx,IN UCHAR Max_Tx_Packets)778 VOID RTMPDeQueuePacket(
779 	IN  PRTMP_ADAPTER   pAd,
780 	IN  BOOLEAN         bIntContext,
781 	IN  UCHAR			QIdx, /* BulkOutPipeId */
782 	IN  UCHAR           Max_Tx_Packets)
783 {
784 	PQUEUE_ENTRY    pEntry = NULL;
785 	PNDIS_PACKET 	pPacket;
786 	NDIS_STATUS     Status = NDIS_STATUS_SUCCESS;
787 	UCHAR           Count=0;
788 	PQUEUE_HEADER   pQueue;
789 	ULONG           FreeNumber[NUM_OF_TX_RING];
790 	UCHAR			QueIdx, sQIdx, eQIdx;
791 	unsigned long	IrqFlags = 0;
792 	BOOLEAN			hasTxDesc = FALSE;
793 	TX_BLK			TxBlk;
794 	TX_BLK			*pTxBlk;
795 
796 #ifdef DBG_DIAGNOSE
797 	BOOLEAN			firstRound;
798 	RtmpDiagStruct	*pDiagStruct = &pAd->DiagStruct;
799 #endif
800 
801 
802 	if (QIdx == NUM_OF_TX_RING)
803 	{
804 		sQIdx = 0;
805 		eQIdx = 3;	// 4 ACs, start from 0.
806 	}
807 	else
808 	{
809 		sQIdx = eQIdx = QIdx;
810 	}
811 
812 	for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++)
813 	{
814 		Count=0;
815 
816 		RT28XX_START_DEQUEUE(pAd, QueIdx, IrqFlags);
817 
818 #ifdef DBG_DIAGNOSE
819 		firstRound = ((QueIdx == 0) ? TRUE : FALSE);
820 #endif // DBG_DIAGNOSE //
821 
822 		while (1)
823 		{
824 			if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |
825 										fRTMP_ADAPTER_RADIO_OFF |
826 										fRTMP_ADAPTER_RESET_IN_PROGRESS |
827 										fRTMP_ADAPTER_HALT_IN_PROGRESS |
828 										fRTMP_ADAPTER_NIC_NOT_EXIST))))
829 			{
830 				RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
831 				return;
832 			}
833 
834 			if (Count >= Max_Tx_Packets)
835 				break;
836 
837 			DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
838 			if (&pAd->TxSwQueue[QueIdx] == NULL)
839 			{
840 #ifdef DBG_DIAGNOSE
841 				if (firstRound == TRUE)
842 					pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][0]++;
843 #endif // DBG_DIAGNOSE //
844 				DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
845 				break;
846 			}
847 
848 
849 			// probe the Queue Head
850 			pQueue = &pAd->TxSwQueue[QueIdx];
851 			if ((pEntry = pQueue->Head) == NULL)
852 			{
853 				DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
854 				break;
855 			}
856 
857 			pTxBlk = &TxBlk;
858 			NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK));
859 			//InitializeQueueHeader(&pTxBlk->TxPacketList);		// Didn't need it because we already memzero it.
860 			pTxBlk->QueIdx = QueIdx;
861 
862 			pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
863 
864 			// Early check to make sure we have enoguh Tx Resource.
865 			hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
866 			if (!hasTxDesc)
867 			{
868 				pAd->PrivateInfo.TxRingFullCnt++;
869 
870 				DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
871 
872 				break;
873 			}
874 
875 			pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
876 			pEntry = RemoveHeadQueue(pQueue);
877 			pTxBlk->TotalFrameNum++;
878 			pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket);	// The real fragment number maybe vary
879 			pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
880 			pTxBlk->pPacket = pPacket;
881 			InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
882 
883 			if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME)
884 			{
885 				// Enhance SW Aggregation Mechanism
886 				if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType))
887 				{
888 					InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
889 					DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
890 					break;
891 				}
892 
893 				do{
894 					if((pEntry = pQueue->Head) == NULL)
895 						break;
896 
897 					// For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation.
898 					pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
899 					FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
900 					hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
901 					if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE))
902 						break;
903 
904 					//Remove the packet from the TxSwQueue and insert into pTxBlk
905 					pEntry = RemoveHeadQueue(pQueue);
906 					ASSERT(pEntry);
907 					pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
908 					pTxBlk->TotalFrameNum++;
909 					pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket);	// The real fragment number maybe vary
910 					pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
911 					InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
912 				}while(1);
913 
914 				if (pTxBlk->TxPacketList.Number == 1)
915 					pTxBlk->TxFrameType = TX_LEGACY_FRAME;
916 			}
917 
918 #ifdef RT2870
919 			DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
920 #endif // RT2870 //
921 
922 			Count += pTxBlk->TxPacketList.Number;
923 
924 				// Do HardTransmit now.
925 #ifdef CONFIG_STA_SUPPORT
926 			IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
927 				Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
928 #endif // CONFIG_STA_SUPPORT //
929 
930 
931 #if 0	// We should not break if HardTransmit failed. Well, at least now we should not!
932 			if (Status != NDIS_STATUS_SUCCESS)
933 			{
934 				DBGPRINT(RT_DEBUG_TRACE /*RT_DEBUG_INFO*/,("RTMPHardTransmit return failed!!!\n"));
935 				break;
936 			}
937 #endif
938 		}
939 
940 		RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
941 
942 #ifdef RT2870
943 		if (!hasTxDesc)
944 			RTUSBKickBulkOut(pAd);
945 #endif // RT2870 //
946 
947 #ifdef BLOCK_NET_IF
948 		if ((pAd->blockQueueTab[QueIdx].SwTxQueueBlockFlag == TRUE)
949 			&& (pAd->TxSwQueue[QueIdx].Number < 1))
950 		{
951 			releaseNetIf(&pAd->blockQueueTab[QueIdx]);
952 		}
953 #endif // BLOCK_NET_IF //
954 
955 	}
956 
957 }
958 
959 
960 /*
961 	========================================================================
962 
963 	Routine Description:
964 		Calculates the duration which is required to transmit out frames
965 	with given size and specified rate.
966 
967 	Arguments:
968 		pAd 	Pointer to our adapter
969 		Rate			Transmit rate
970 		Size			Frame size in units of byte
971 
972 	Return Value:
973 		Duration number in units of usec
974 
975 	IRQL = PASSIVE_LEVEL
976 	IRQL = DISPATCH_LEVEL
977 
978 	Note:
979 
980 	========================================================================
981 */
RTMPCalcDuration(IN PRTMP_ADAPTER pAd,IN UCHAR Rate,IN ULONG Size)982 USHORT	RTMPCalcDuration(
983 	IN	PRTMP_ADAPTER	pAd,
984 	IN	UCHAR			Rate,
985 	IN	ULONG			Size)
986 {
987 	ULONG	Duration = 0;
988 
989 	if (Rate < RATE_FIRST_OFDM_RATE) // CCK
990 	{
991 		if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED))
992 			Duration = 96;	// 72+24 preamble+plcp
993 		else
994 			Duration = 192; // 144+48 preamble+plcp
995 
996 		Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]);
997 		if ((Size << 4) % RateIdTo500Kbps[Rate])
998 			Duration ++;
999 	}
1000 	else if (Rate <= RATE_LAST_OFDM_RATE)// OFDM rates
1001 	{
1002 		Duration = 20 + 6;		// 16+4 preamble+plcp + Signal Extension
1003 		Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
1004 		if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
1005 			Duration += 4;
1006 	}
1007 	else	//mimo rate
1008 	{
1009 		Duration = 20 + 6;		// 16+4 preamble+plcp + Signal Extension
1010 	}
1011 
1012 	return (USHORT)Duration;
1013 }
1014 
1015 
1016 /*
1017 	========================================================================
1018 
1019 	Routine Description:
1020 		Calculates the duration which is required to transmit out frames
1021 	with given size and specified rate.
1022 
1023 	Arguments:
1024 		pTxWI		Pointer to head of each MPDU to HW.
1025 		Ack 		Setting for Ack requirement bit
1026 		Fragment	Setting for Fragment bit
1027 		RetryMode	Setting for retry mode
1028 		Ifs 		Setting for IFS gap
1029 		Rate		Setting for transmit rate
1030 		Service 	Setting for service
1031 		Length		Frame length
1032 		TxPreamble	Short or Long preamble when using CCK rates
1033 		QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1034 
1035 	Return Value:
1036 		None
1037 
1038 	IRQL = PASSIVE_LEVEL
1039 	IRQL = DISPATCH_LEVEL
1040 
1041     See also : BASmartHardTransmit()    !!!
1042 
1043 	========================================================================
1044 */
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,IN UCHAR BASize,IN UCHAR WCID,IN ULONG Length,IN UCHAR PID,IN UCHAR TID,IN UCHAR TxRate,IN UCHAR Txopmode,IN BOOLEAN CfAck,IN HTTRANSMIT_SETTING * pTransmit)1045 VOID RTMPWriteTxWI(
1046 	IN	PRTMP_ADAPTER	pAd,
1047 	IN	PTXWI_STRUC 	pOutTxWI,
1048 	IN	BOOLEAN			FRAG,
1049 	IN	BOOLEAN			CFACK,
1050 	IN	BOOLEAN			InsTimestamp,
1051 	IN	BOOLEAN 		AMPDU,
1052 	IN	BOOLEAN 		Ack,
1053 	IN	BOOLEAN 		NSeq,		// HW new a sequence.
1054 	IN	UCHAR			BASize,
1055 	IN	UCHAR			WCID,
1056 	IN	ULONG			Length,
1057 	IN	UCHAR 			PID,
1058 	IN	UCHAR			TID,
1059 	IN	UCHAR			TxRate,
1060 	IN	UCHAR			Txopmode,
1061 	IN	BOOLEAN			CfAck,
1062 	IN	HTTRANSMIT_SETTING	*pTransmit)
1063 {
1064 	PMAC_TABLE_ENTRY	pMac = NULL;
1065 	TXWI_STRUC 		TxWI;
1066 	PTXWI_STRUC 	pTxWI;
1067 
1068 	if (WCID < MAX_LEN_OF_MAC_TABLE)
1069 		pMac = &pAd->MacTab.Content[WCID];
1070 
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(&TxWI, TXWI_SIZE);
1077 	pTxWI = &TxWI;
1078 
1079 	pTxWI->FRAG= FRAG;
1080 
1081 	pTxWI->CFACK = CFACK;
1082 	pTxWI->TS= InsTimestamp;
1083 	pTxWI->AMPDU = AMPDU;
1084 	pTxWI->ACK = Ack;
1085 	pTxWI->txop= Txopmode;
1086 
1087 	pTxWI->NSEQ = NSeq;
1088 	// John tune the performace with Intel Client in 20 MHz performance
1089 #ifdef DOT11_N_SUPPORT
1090 	BASize = pAd->CommonCfg.TxBASize;
1091 
1092 	if( BASize >7 )
1093 		BASize =7;
1094 	pTxWI->BAWinSize = BASize;
1095 	pTxWI->ShortGI = pTransmit->field.ShortGI;
1096 	pTxWI->STBC = pTransmit->field.STBC;
1097 #endif // DOT11_N_SUPPORT //
1098 
1099 	pTxWI->WirelessCliID = WCID;
1100 	pTxWI->MPDUtotalByteCount = Length;
1101 	pTxWI->PacketId = PID;
1102 
1103 	// If CCK or OFDM, BW must be 20
1104 	pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1105 #ifdef DOT11N_DRAFT3
1106 	if (pTxWI->BW)
1107 		pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1108 #endif // DOT11N_DRAFT3 //
1109 
1110 	pTxWI->MCS = pTransmit->field.MCS;
1111 	pTxWI->PHYMODE = pTransmit->field.MODE;
1112 	pTxWI->CFACK = CfAck;
1113 
1114 #ifdef DOT11_N_SUPPORT
1115 	if (pMac)
1116 	{
1117 		if (pAd->CommonCfg.bMIMOPSEnable)
1118 		{
1119 			if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1120 			{
1121 				// Dynamic MIMO Power Save Mode
1122 				pTxWI->MIMOps = 1;
1123 			}
1124 			else if (pMac->MmpsMode == MMPS_STATIC)
1125 			{
1126 				// Static MIMO Power Save Mode
1127 				if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1128 				{
1129 					pTxWI->MCS = 7;
1130 					pTxWI->MIMOps = 0;
1131 				}
1132 			}
1133 		}
1134 		//pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;
1135 		if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled))
1136 		{
1137 			pTxWI->MpduDensity = 7;
1138 		}
1139 		else
1140 		{
1141 			pTxWI->MpduDensity = pMac->MpduDensity;
1142 		}
1143 	}
1144 #endif // DOT11_N_SUPPORT //
1145 
1146 	pTxWI->PacketId = pTxWI->MCS;
1147 	NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC));
1148 }
1149 
1150 
RTMPWriteTxWI_Data(IN PRTMP_ADAPTER pAd,IN OUT PTXWI_STRUC pTxWI,IN TX_BLK * pTxBlk)1151 VOID RTMPWriteTxWI_Data(
1152 	IN	PRTMP_ADAPTER		pAd,
1153 	IN	OUT PTXWI_STRUC		pTxWI,
1154 	IN	TX_BLK				*pTxBlk)
1155 {
1156 	HTTRANSMIT_SETTING	*pTransmit;
1157 	PMAC_TABLE_ENTRY	pMacEntry;
1158 #ifdef DOT11_N_SUPPORT
1159 	UCHAR				BASize;
1160 #endif // DOT11_N_SUPPORT //
1161 
1162 
1163 	ASSERT(pTxWI);
1164 
1165 	pTransmit = pTxBlk->pTransmit;
1166 	pMacEntry = pTxBlk->pMacEntry;
1167 
1168 
1169 	//
1170 	// Always use Long preamble before verifiation short preamble functionality works well.
1171 	// Todo: remove the following line if short preamble functionality works
1172 	//
1173 	OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1174 	NdisZeroMemory(pTxWI, TXWI_SIZE);
1175 
1176 	pTxWI->FRAG		= TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1177 	pTxWI->ACK		= TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1178 	pTxWI->txop		= pTxBlk->FrameGap;
1179 
1180 #ifdef CONFIG_STA_SUPPORT
1181 #ifdef QOS_DLS_SUPPORT
1182 	if (pMacEntry &&
1183 		(pAd->StaCfg.BssType == BSS_INFRA) &&
1184 		(pMacEntry->ValidAsDls == TRUE))
1185 		pTxWI->WirelessCliID = BSSID_WCID;
1186 	else
1187 #endif // QOS_DLS_SUPPORT //
1188 #endif // CONFIG_STA_SUPPORT //
1189 		pTxWI->WirelessCliID		= pTxBlk->Wcid;
1190 
1191 	pTxWI->MPDUtotalByteCount	= pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1192 	pTxWI->CFACK				= TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
1193 
1194 	// If CCK or OFDM, BW must be 20
1195 	pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1196 #ifdef DOT11_N_SUPPORT
1197 #ifdef DOT11N_DRAFT3
1198 	if (pTxWI->BW)
1199 		pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1200 #endif // DOT11N_DRAFT3 //
1201 	pTxWI->AMPDU	= ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
1202 
1203 	// John tune the performace with Intel Client in 20 MHz performance
1204 	BASize = pAd->CommonCfg.TxBASize;
1205 	if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry))
1206 	{
1207 		UCHAR		RABAOriIdx = 0;	//The RA's BA Originator table index.
1208 
1209 		RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
1210 		BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1211 	}
1212 
1213 #if 0 // 3*3
1214 	if (BASize > 7)
1215 		BASize = 7;
1216 #endif
1217 
1218 	pTxWI->TxBF = pTransmit->field.TxBF;
1219 	pTxWI->BAWinSize = BASize;
1220 	pTxWI->ShortGI = pTransmit->field.ShortGI;
1221 	pTxWI->STBC = pTransmit->field.STBC;
1222 #endif // DOT11_N_SUPPORT //
1223 
1224 	pTxWI->MCS = pTransmit->field.MCS;
1225 	pTxWI->PHYMODE = pTransmit->field.MODE;
1226 
1227 #ifdef DOT11_N_SUPPORT
1228 	if (pMacEntry)
1229 	{
1230 		if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1231 		{
1232 			// Dynamic MIMO Power Save Mode
1233 			pTxWI->MIMOps = 1;
1234 		}
1235 		else if (pMacEntry->MmpsMode == MMPS_STATIC)
1236 		{
1237 			// Static MIMO Power Save Mode
1238 			if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1239 			{
1240 				pTxWI->MCS = 7;
1241 				pTxWI->MIMOps = 0;
1242 			}
1243 		}
1244 
1245 		if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled))
1246 		{
1247 			pTxWI->MpduDensity = 7;
1248 		}
1249 		else
1250 		{
1251 			pTxWI->MpduDensity = pMacEntry->MpduDensity;
1252 		}
1253 	}
1254 #endif // DOT11_N_SUPPORT //
1255 
1256 #ifdef DBG_DIAGNOSE
1257 		if (pTxBlk->QueIdx== 0)
1258 		{
1259 			pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1260 			pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1261 		}
1262 #endif // DBG_DIAGNOSE //
1263 
1264 	// for rate adapation
1265 	pTxWI->PacketId = pTxWI->MCS;
1266 }
1267 
1268 
RTMPWriteTxWI_Cache(IN PRTMP_ADAPTER pAd,IN OUT PTXWI_STRUC pTxWI,IN TX_BLK * pTxBlk)1269 VOID RTMPWriteTxWI_Cache(
1270 	IN	PRTMP_ADAPTER		pAd,
1271 	IN	OUT PTXWI_STRUC		pTxWI,
1272 	IN	TX_BLK				*pTxBlk)
1273 {
1274 	PHTTRANSMIT_SETTING	/*pTxHTPhyMode,*/ pTransmit;
1275 	PMAC_TABLE_ENTRY	pMacEntry;
1276 
1277 	//
1278 	// update TXWI
1279 	//
1280 	pMacEntry = pTxBlk->pMacEntry;
1281 	pTransmit = pTxBlk->pTransmit;
1282 
1283 	if (pMacEntry->bAutoTxRateSwitch)
1284 	{
1285 		pTxWI->txop = IFS_HTTXOP;
1286 
1287 		// If CCK or OFDM, BW must be 20
1288 		pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1289 		pTxWI->ShortGI = pTransmit->field.ShortGI;
1290 		pTxWI->STBC = pTransmit->field.STBC;
1291 
1292 		pTxWI->MCS = pTransmit->field.MCS;
1293 		pTxWI->PHYMODE = pTransmit->field.MODE;
1294 
1295 		// set PID for TxRateSwitching
1296 		pTxWI->PacketId = pTransmit->field.MCS;
1297 	}
1298 
1299 #ifdef DOT11_N_SUPPORT
1300 	pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE);
1301 	pTxWI->MIMOps = 0;
1302 
1303 #ifdef DOT11N_DRAFT3
1304 	if (pTxWI->BW)
1305 		pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1306 #endif // DOT11N_DRAFT3 //
1307 
1308 	if (pAd->CommonCfg.bMIMOPSEnable)
1309 	{
1310 		// MIMO Power Save Mode
1311 		if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1312 		{
1313 			// Dynamic MIMO Power Save Mode
1314 			pTxWI->MIMOps = 1;
1315 		}
1316 		else if (pMacEntry->MmpsMode == MMPS_STATIC)
1317 		{
1318 			// Static MIMO Power Save Mode
1319 			if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7))
1320 			{
1321 				pTxWI->MCS = 7;
1322 				pTxWI->MIMOps = 0;
1323 			}
1324 		}
1325 	}
1326 #endif // DOT11_N_SUPPORT //
1327 
1328 #ifdef DBG_DIAGNOSE
1329 	if (pTxBlk->QueIdx== 0)
1330 	{
1331 		pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1332 		pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1333 	}
1334 #endif // DBG_DIAGNOSE //
1335 
1336 	pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1337 
1338 }
1339 
1340 
1341 /*
1342 	========================================================================
1343 
1344 	Routine Description:
1345 		Calculates the duration which is required to transmit out frames
1346 	with given size and specified rate.
1347 
1348 	Arguments:
1349 		pTxD		Pointer to transmit descriptor
1350 		Ack 		Setting for Ack requirement bit
1351 		Fragment	Setting for Fragment bit
1352 		RetryMode	Setting for retry mode
1353 		Ifs 		Setting for IFS gap
1354 		Rate		Setting for transmit rate
1355 		Service 	Setting for service
1356 		Length		Frame length
1357 		TxPreamble	Short or Long preamble when using CCK rates
1358 		QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1359 
1360 	Return Value:
1361 		None
1362 
1363 	IRQL = PASSIVE_LEVEL
1364 	IRQL = DISPATCH_LEVEL
1365 
1366 	========================================================================
1367 */
RTMPWriteTxDescriptor(IN PRTMP_ADAPTER pAd,IN PTXD_STRUC pTxD,IN BOOLEAN bWIV,IN UCHAR QueueSEL)1368 VOID RTMPWriteTxDescriptor(
1369 	IN	PRTMP_ADAPTER	pAd,
1370 	IN	PTXD_STRUC		pTxD,
1371 	IN	BOOLEAN 		bWIV,
1372 	IN	UCHAR			QueueSEL)
1373 {
1374 	//
1375 	// Always use Long preamble before verifiation short preamble functionality works well.
1376 	// Todo: remove the following line if short preamble functionality works
1377 	//
1378 	OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1379 
1380 	pTxD->WIV	= (bWIV) ? 1: 0;
1381 	pTxD->QSEL= (QueueSEL);
1382 	//RT2860c??  fixed using EDCA queue for test...  We doubt Queue1 has problem.  2006-09-26 Jan
1383 	//pTxD->QSEL= FIFO_EDCA;
1384 	if (pAd->bGenOneHCCA == TRUE)
1385 		pTxD->QSEL= FIFO_HCCA;
1386 	pTxD->DMADONE = 0;
1387 }
1388 
1389 
1390 // should be called only when -
1391 // 1. MEADIA_CONNECTED
1392 // 2. AGGREGATION_IN_USED
1393 // 3. Fragmentation not in used
1394 // 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible
TxFrameIsAggregatible(IN PRTMP_ADAPTER pAd,IN PUCHAR pPrevAddr1,IN PUCHAR p8023hdr)1395 BOOLEAN TxFrameIsAggregatible(
1396 	IN	PRTMP_ADAPTER	pAd,
1397 	IN	PUCHAR			pPrevAddr1,
1398 	IN	PUCHAR			p8023hdr)
1399 {
1400 
1401 	// can't aggregate EAPOL (802.1x) frame
1402 	if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1403 		return FALSE;
1404 
1405 	// can't aggregate multicast/broadcast frame
1406 	if (p8023hdr[0] & 0x01)
1407 		return FALSE;
1408 
1409 	if (INFRA_ON(pAd)) // must be unicast to AP
1410 		return TRUE;
1411 	else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA
1412 		return TRUE;
1413 	else
1414 		return FALSE;
1415 }
1416 
1417 
1418 /*
1419 	========================================================================
1420 
1421 	Routine Description:
1422 	   Check the MSDU Aggregation policy
1423 	1.HT aggregation is A-MSDU
1424 	2.legaacy rate aggregation is software aggregation by Ralink.
1425 
1426 	Arguments:
1427 
1428 	Return Value:
1429 
1430 	Note:
1431 
1432 	========================================================================
1433 */
PeerIsAggreOn(IN PRTMP_ADAPTER pAd,IN ULONG TxRate,IN PMAC_TABLE_ENTRY pMacEntry)1434 BOOLEAN PeerIsAggreOn(
1435 	IN	PRTMP_ADAPTER	pAd,
1436 	IN	ULONG		   TxRate,
1437 	IN	PMAC_TABLE_ENTRY pMacEntry)
1438 {
1439 	ULONG	AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
1440 
1441 	if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags))
1442 	{
1443 #ifdef DOT11_N_SUPPORT
1444 		if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX)
1445 		{
1446 			return TRUE;
1447 		}
1448 #endif // DOT11_N_SUPPORT //
1449 
1450 #ifdef AGGREGATION_SUPPORT
1451 		if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
1452 		{	// legacy  Ralink Aggregation support
1453 			return TRUE;
1454 		}
1455 #endif // AGGREGATION_SUPPORT //
1456 	}
1457 
1458 	return FALSE;
1459 
1460 }
1461 
1462 /*
1463 	========================================================================
1464 
1465 	Routine Description:
1466 		Check and fine the packet waiting in SW queue with highest priority
1467 
1468 	Arguments:
1469 		pAd Pointer to our adapter
1470 
1471 	Return Value:
1472 		pQueue		Pointer to Waiting Queue
1473 
1474 	IRQL = DISPATCH_LEVEL
1475 
1476 	Note:
1477 
1478 	========================================================================
1479 */
RTMPCheckTxSwQueue(IN PRTMP_ADAPTER pAd,OUT PUCHAR pQueIdx)1480 PQUEUE_HEADER	RTMPCheckTxSwQueue(
1481 	IN	PRTMP_ADAPTER	pAd,
1482 	OUT PUCHAR			pQueIdx)
1483 {
1484 
1485 	ULONG	Number;
1486 	// 2004-11-15 to be removed. test aggregation only
1487 //	if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2))
1488 //		 return NULL;
1489 
1490 	Number = pAd->TxSwQueue[QID_AC_BK].Number
1491 			 + pAd->TxSwQueue[QID_AC_BE].Number
1492 			 + pAd->TxSwQueue[QID_AC_VI].Number
1493 			 + pAd->TxSwQueue[QID_AC_VO].Number
1494 			 + pAd->TxSwQueue[QID_HCCA].Number;
1495 
1496 	if (pAd->TxSwQueue[QID_AC_VO].Head != NULL)
1497 	{
1498 		*pQueIdx = QID_AC_VO;
1499 		return (&pAd->TxSwQueue[QID_AC_VO]);
1500 	}
1501 	else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL)
1502 	{
1503 		*pQueIdx = QID_AC_VI;
1504 		return (&pAd->TxSwQueue[QID_AC_VI]);
1505 	}
1506 	else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL)
1507 	{
1508 		*pQueIdx = QID_AC_BE;
1509 		return (&pAd->TxSwQueue[QID_AC_BE]);
1510 	}
1511 	else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL)
1512 	{
1513 		*pQueIdx = QID_AC_BK;
1514 		return (&pAd->TxSwQueue[QID_AC_BK]);
1515 	}
1516 	else if (pAd->TxSwQueue[QID_HCCA].Head != NULL)
1517 	{
1518 		*pQueIdx = QID_HCCA;
1519 		return (&pAd->TxSwQueue[QID_HCCA]);
1520 	}
1521 
1522 	// No packet pending in Tx Sw queue
1523 	*pQueIdx = QID_AC_BK;
1524 
1525 	return (NULL);
1526 }
1527 
1528 
1529 
1530 /*
1531 	========================================================================
1532 
1533 	Routine Description:
1534 		Suspend MSDU transmission
1535 
1536 	Arguments:
1537 		pAd 	Pointer to our adapter
1538 
1539 	Return Value:
1540 		None
1541 
1542 	Note:
1543 
1544 	========================================================================
1545 */
RTMPSuspendMsduTransmission(IN PRTMP_ADAPTER pAd)1546 VOID	RTMPSuspendMsduTransmission(
1547 	IN	PRTMP_ADAPTER	pAd)
1548 {
1549 	DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n"));
1550 
1551 
1552 	//
1553 	// Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
1554 	// use Lowbound as R66 value on ScanNextChannel(...)
1555 	//
1556 	RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue);
1557 
1558 	// set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)
1559 	//RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd)));
1560 	RTMPSetAGCInitValue(pAd, BW_20);
1561 
1562 	RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1563 	//RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000);		// abort all TX rings
1564 }
1565 
1566 
1567 /*
1568 	========================================================================
1569 
1570 	Routine Description:
1571 		Resume MSDU transmission
1572 
1573 	Arguments:
1574 		pAd 	Pointer to our adapter
1575 
1576 	Return Value:
1577 		None
1578 
1579 	IRQL = DISPATCH_LEVEL
1580 
1581 	Note:
1582 
1583 	========================================================================
1584 */
RTMPResumeMsduTransmission(IN PRTMP_ADAPTER pAd)1585 VOID RTMPResumeMsduTransmission(
1586 	IN	PRTMP_ADAPTER	pAd)
1587 {
1588 //    UCHAR			IrqState;
1589 
1590 	DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
1591 
1592 
1593 	RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue);
1594 
1595 	RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1596 // sample, for IRQ LOCK to SEM LOCK
1597 //    IrqState = pAd->irq_disabled;
1598 //	if (IrqState)
1599 //		RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1600 //    else
1601 	RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1602 }
1603 
1604 
deaggregate_AMSDU_announce(IN PRTMP_ADAPTER pAd,PNDIS_PACKET pPacket,IN PUCHAR pData,IN ULONG DataSize)1605 UINT deaggregate_AMSDU_announce(
1606 	IN	PRTMP_ADAPTER	pAd,
1607 	PNDIS_PACKET		pPacket,
1608 	IN	PUCHAR			pData,
1609 	IN	ULONG			DataSize)
1610 {
1611 	USHORT 			PayloadSize;
1612 	USHORT 			SubFrameSize;
1613 	PHEADER_802_3 	pAMSDUsubheader;
1614 	UINT			nMSDU;
1615     UCHAR			Header802_3[14];
1616 
1617 	PUCHAR			pPayload, pDA, pSA, pRemovedLLCSNAP;
1618 	PNDIS_PACKET	pClonePacket;
1619 
1620 
1621 
1622 	nMSDU = 0;
1623 
1624 	while (DataSize > LENGTH_802_3)
1625 	{
1626 
1627 		nMSDU++;
1628 
1629 		//hex_dump("subheader", pData, 64);
1630 		pAMSDUsubheader = (PHEADER_802_3)pData;
1631 		//pData += LENGTH_802_3;
1632 		PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8);
1633 		SubFrameSize = PayloadSize + LENGTH_802_3;
1634 
1635 
1636 		if ((DataSize < SubFrameSize) || (PayloadSize > 1518 ))
1637 		{
1638 			break;
1639 		}
1640 
1641 		//printk("%d subframe: Size = %d\n",  nMSDU, PayloadSize);
1642 
1643 		pPayload = pData + LENGTH_802_3;
1644 		pDA = pData;
1645 		pSA = pData + MAC_ADDR_LEN;
1646 
1647 		// convert to 802.3 header
1648         CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP);
1649 
1650 #ifdef CONFIG_STA_SUPPORT
1651 		if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) )
1652 		{
1653 		    // avoid local heap overflow, use dyanamic allocation
1654 		   MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
1655 		   memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize);
1656 		   Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize;
1657 		   WpaEAPOLKeyAction(pAd, Elem);
1658 		   kfree(Elem);
1659 		}
1660 #endif // CONFIG_STA_SUPPORT //
1661 
1662 #ifdef CONFIG_STA_SUPPORT
1663 		IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1664 		{
1665 	        	if (pRemovedLLCSNAP)
1666 	        	{
1667 	    			pPayload -= LENGTH_802_3;
1668 	    			PayloadSize += LENGTH_802_3;
1669 	    			NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3);
1670 	        	}
1671 		}
1672 #endif // CONFIG_STA_SUPPORT //
1673 
1674 		pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
1675 		if (pClonePacket)
1676 		{
1677 #ifdef CONFIG_STA_SUPPORT
1678 			IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1679 				ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket));
1680 #endif // CONFIG_STA_SUPPORT //
1681 		}
1682 
1683 
1684 		// A-MSDU has padding to multiple of 4 including subframe header.
1685 		// align SubFrameSize up to multiple of 4
1686 		SubFrameSize = (SubFrameSize+3)&(~0x3);
1687 
1688 
1689 		if (SubFrameSize > 1528 || SubFrameSize < 32)
1690 		{
1691 			break;
1692 		}
1693 
1694 		if (DataSize > SubFrameSize)
1695 		{
1696 			pData += SubFrameSize;
1697 			DataSize -= SubFrameSize;
1698 		}
1699 		else
1700 		{
1701 			// end of A-MSDU
1702 			DataSize = 0;
1703 		}
1704 	}
1705 
1706 	// finally release original rx packet
1707 	RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1708 
1709 	return nMSDU;
1710 }
1711 
1712 
BA_Reorder_AMSDU_Annnounce(IN PRTMP_ADAPTER pAd,IN PNDIS_PACKET pPacket)1713 UINT BA_Reorder_AMSDU_Annnounce(
1714 	IN	PRTMP_ADAPTER	pAd,
1715 	IN	PNDIS_PACKET	pPacket)
1716 {
1717 	PUCHAR			pData;
1718 	USHORT			DataSize;
1719 	UINT			nMSDU = 0;
1720 
1721 	pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
1722 	DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
1723 
1724 	nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
1725 
1726 	return nMSDU;
1727 }
1728 
1729 
1730 /*
1731 	==========================================================================
1732 	Description:
1733 		Look up the MAC address in the MAC table. Return NULL if not found.
1734 	Return:
1735 		pEntry - pointer to the MAC entry; NULL is not found
1736 	==========================================================================
1737 */
MacTableLookup(IN PRTMP_ADAPTER pAd,PUCHAR pAddr)1738 MAC_TABLE_ENTRY *MacTableLookup(
1739 	IN PRTMP_ADAPTER pAd,
1740 	PUCHAR pAddr)
1741 {
1742 	ULONG HashIdx;
1743 	MAC_TABLE_ENTRY *pEntry = NULL;
1744 
1745 	HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1746 	pEntry = pAd->MacTab.Hash[HashIdx];
1747 
1748 	while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh))
1749 	{
1750 		if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1751 		{
1752 			break;
1753 		}
1754 		else
1755 			pEntry = pEntry->pNext;
1756 	}
1757 
1758 	return pEntry;
1759 }
1760 
MacTableInsertEntry(IN PRTMP_ADAPTER pAd,IN PUCHAR pAddr,IN UCHAR apidx,IN BOOLEAN CleanAll)1761 MAC_TABLE_ENTRY *MacTableInsertEntry(
1762 	IN  PRTMP_ADAPTER   pAd,
1763 	IN  PUCHAR			pAddr,
1764 	IN	UCHAR			apidx,
1765 	IN BOOLEAN	CleanAll)
1766 {
1767 	UCHAR HashIdx;
1768 	int i, FirstWcid;
1769 	MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
1770 
1771 	// if FULL, return
1772 	if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
1773 		return NULL;
1774 
1775 	FirstWcid = 1;
1776 #ifdef CONFIG_STA_SUPPORT
1777 	IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1778 	if (pAd->StaCfg.BssType == BSS_INFRA)
1779 		FirstWcid = 2;
1780 #endif // CONFIG_STA_SUPPORT //
1781 
1782 	// allocate one MAC entry
1783 	NdisAcquireSpinLock(&pAd->MacTabLock);
1784 	for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++)   // skip entry#0 so that "entry index == AID" for fast lookup
1785 	{
1786 		// pick up the first available vacancy
1787 		if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
1788 			(pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
1789 			(pAd->MacTab.Content[i].ValidAsApCli== FALSE) &&
1790 			(pAd->MacTab.Content[i].ValidAsMesh == FALSE)
1791 #ifdef CONFIG_STA_SUPPORT
1792 #ifdef QOS_DLS_SUPPORT
1793 			&& (pAd->MacTab.Content[i].ValidAsDls == FALSE)
1794 #endif // QOS_DLS_SUPPORT //
1795 #endif // CONFIG_STA_SUPPORT //
1796 			)
1797 		{
1798 			pEntry = &pAd->MacTab.Content[i];
1799 			if (CleanAll == TRUE)
1800 			{
1801 				pEntry->MaxSupportedRate = RATE_11;
1802 				pEntry->CurrTxRate = RATE_11;
1803 				NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1804 				pEntry->PairwiseKey.KeyLen = 0;
1805 				pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1806 			}
1807 #ifdef CONFIG_STA_SUPPORT
1808 #ifdef QOS_DLS_SUPPORT
1809 			if (apidx >= MIN_NET_DEVICE_FOR_DLS)
1810 			{
1811 				pEntry->ValidAsCLI = FALSE;
1812 				pEntry->ValidAsWDS = FALSE;
1813 				pEntry->ValidAsApCli = FALSE;
1814 				pEntry->ValidAsMesh = FALSE;
1815 				pEntry->ValidAsDls = TRUE;
1816 				pEntry->isCached = FALSE;
1817 			}
1818 			else
1819 #endif // QOS_DLS_SUPPORT //
1820 #endif // CONFIG_STA_SUPPORT //
1821 			{
1822 
1823 #ifdef CONFIG_STA_SUPPORT
1824 				IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1825 				{
1826 					pEntry->ValidAsCLI = TRUE;
1827 					pEntry->ValidAsWDS = FALSE;
1828 					pEntry->ValidAsApCli = FALSE;
1829 					pEntry->ValidAsMesh = FALSE;
1830 					pEntry->ValidAsDls = FALSE;
1831 				}
1832 #endif // CONFIG_STA_SUPPORT //
1833 			}
1834 
1835 			pEntry->bIAmBadAtheros = FALSE;
1836 			pEntry->pAd = pAd;
1837 			pEntry->CMTimerRunning = FALSE;
1838 			pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
1839 			pEntry->RSNIE_Len = 0;
1840 			NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
1841 			pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
1842 
1843 			if (pEntry->ValidAsMesh)
1844 				pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH);
1845 			else if (pEntry->ValidAsApCli)
1846 				pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI);
1847 			else if (pEntry->ValidAsWDS)
1848 				pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS);
1849 #ifdef CONFIG_STA_SUPPORT
1850 #ifdef QOS_DLS_SUPPORT
1851 			else if (pEntry->ValidAsDls)
1852 				pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_DLS);
1853 #endif // QOS_DLS_SUPPORT //
1854 #endif // CONFIG_STA_SUPPORT //
1855 			else
1856 				pEntry->apidx = apidx;
1857 
1858 			{
1859 
1860 #ifdef CONFIG_STA_SUPPORT
1861 				IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1862 				{
1863 					pEntry->AuthMode = pAd->StaCfg.AuthMode;
1864 					pEntry->WepStatus = pAd->StaCfg.WepStatus;
1865 					pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
1866 				}
1867 #endif // CONFIG_STA_SUPPORT //
1868 			}
1869 
1870 			pEntry->GTKState = REKEY_NEGOTIATING;
1871 			pEntry->PairwiseKey.KeyLen = 0;
1872 			pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1873 #ifdef CONFIG_STA_SUPPORT
1874 #ifdef QOS_DLS_SUPPORT
1875 			if (pEntry->ValidAsDls == TRUE)
1876 				pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
1877 #endif //QOS_DLS_SUPPORT
1878 #endif // CONFIG_STA_SUPPORT //
1879 			pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
1880 			pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
1881 			COPY_MAC_ADDR(pEntry->Addr, pAddr);
1882 			pEntry->Sst = SST_NOT_AUTH;
1883 			pEntry->AuthState = AS_NOT_AUTH;
1884 			pEntry->Aid = (USHORT)i;  //0;
1885 			pEntry->CapabilityInfo = 0;
1886 			pEntry->PsMode = PWR_ACTIVE;
1887 			pEntry->PsQIdleCount = 0;
1888 			pEntry->NoDataIdleCount = 0;
1889 			pEntry->ContinueTxFailCnt = 0;
1890 			InitializeQueueHeader(&pEntry->PsQueue);
1891 
1892 
1893 			pAd->MacTab.Size ++;
1894 			// Add this entry into ASIC RX WCID search table
1895 			RT28XX_STA_ENTRY_ADD(pAd, pEntry);
1896 
1897 			DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size));
1898 			break;
1899 		}
1900 	}
1901 
1902 	// add this MAC entry into HASH table
1903 	if (pEntry)
1904 	{
1905 		HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1906 		if (pAd->MacTab.Hash[HashIdx] == NULL)
1907 		{
1908 			pAd->MacTab.Hash[HashIdx] = pEntry;
1909 		}
1910 		else
1911 		{
1912 			pCurrEntry = pAd->MacTab.Hash[HashIdx];
1913 			while (pCurrEntry->pNext != NULL)
1914 				pCurrEntry = pCurrEntry->pNext;
1915 			pCurrEntry->pNext = pEntry;
1916 		}
1917 	}
1918 
1919 	NdisReleaseSpinLock(&pAd->MacTabLock);
1920 	return pEntry;
1921 }
1922 
1923 /*
1924 	==========================================================================
1925 	Description:
1926 		Delete a specified client from MAC table
1927 	==========================================================================
1928  */
MacTableDeleteEntry(IN PRTMP_ADAPTER pAd,IN USHORT wcid,IN PUCHAR pAddr)1929 BOOLEAN MacTableDeleteEntry(
1930 	IN PRTMP_ADAPTER pAd,
1931 	IN USHORT wcid,
1932 	IN PUCHAR pAddr)
1933 {
1934 	USHORT HashIdx;
1935 	MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
1936 	BOOLEAN Cancelled;
1937 	//USHORT	offset;	// unused variable
1938 	//UCHAR	j;			// unused variable
1939 
1940 	if (wcid >= MAX_LEN_OF_MAC_TABLE)
1941 		return FALSE;
1942 
1943 	NdisAcquireSpinLock(&pAd->MacTabLock);
1944 
1945 	HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1946 	//pEntry = pAd->MacTab.Hash[HashIdx];
1947 	pEntry = &pAd->MacTab.Content[wcid];
1948 
1949 	if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh
1950 #ifdef CONFIG_STA_SUPPORT
1951 #ifdef QOS_DLS_SUPPORT
1952  		|| pEntry->ValidAsDls
1953 #endif // QOS_DLS_SUPPORT //
1954 #endif // CONFIG_STA_SUPPORT //
1955 		))
1956 	{
1957 		if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1958 		{
1959 
1960 			// Delete this entry from ASIC on-chip WCID Table
1961 			RT28XX_STA_ENTRY_MAC_RESET(pAd, wcid);
1962 
1963 #ifdef DOT11_N_SUPPORT
1964 			// free resources of BA
1965 			BASessionTearDownALL(pAd, pEntry->Aid);
1966 #endif // DOT11_N_SUPPORT //
1967 
1968 
1969 			pPrevEntry = NULL;
1970 			pProbeEntry = pAd->MacTab.Hash[HashIdx];
1971 			ASSERT(pProbeEntry);
1972 
1973 			// update Hash list
1974 			do
1975 			{
1976 				if (pProbeEntry == pEntry)
1977 				{
1978 					if (pPrevEntry == NULL)
1979 					{
1980 						pAd->MacTab.Hash[HashIdx] = pEntry->pNext;
1981 					}
1982 					else
1983 					{
1984 						pPrevEntry->pNext = pEntry->pNext;
1985 					}
1986 					break;
1987 				}
1988 
1989 				pPrevEntry = pProbeEntry;
1990 				pProbeEntry = pProbeEntry->pNext;
1991 			} while (pProbeEntry);
1992 
1993 			// not found !!!
1994 			ASSERT(pProbeEntry != NULL);
1995 
1996 			RT28XX_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
1997 
1998 
1999 		if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
2000 		{
2001 			RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
2002 			pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
2003 		}
2004 
2005 
2006    			NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
2007 			pAd->MacTab.Size --;
2008 			DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size));
2009 		}
2010 		else
2011 		{
2012 			printk("\n%s: Impossible Wcid = %d !!!!!\n", __func__, wcid);
2013 		}
2014 	}
2015 
2016 	NdisReleaseSpinLock(&pAd->MacTabLock);
2017 
2018 	//Reset operating mode when no Sta.
2019 	if (pAd->MacTab.Size == 0)
2020 	{
2021 #ifdef DOT11_N_SUPPORT
2022 		pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
2023 #endif // DOT11_N_SUPPORT //
2024 		AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/);
2025 	}
2026 
2027 	return TRUE;
2028 }
2029 
2030 
2031 /*
2032 	==========================================================================
2033 	Description:
2034 		This routine reset the entire MAC table. All packets pending in
2035 		the power-saving queues are freed here.
2036 	==========================================================================
2037  */
MacTableReset(IN PRTMP_ADAPTER pAd)2038 VOID MacTableReset(
2039 	IN  PRTMP_ADAPTER  pAd)
2040 {
2041 	int         i;
2042 
2043 	DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
2044 	//NdisAcquireSpinLock(&pAd->MacTabLock);
2045 
2046 	for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
2047 	{
2048 		if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
2049 	   {
2050 
2051 #ifdef DOT11_N_SUPPORT
2052 			// free resources of BA
2053 			BASessionTearDownALL(pAd, i);
2054 #endif // DOT11_N_SUPPORT //
2055 
2056 			pAd->MacTab.Content[i].ValidAsCLI = FALSE;
2057 
2058 
2059 
2060 #ifdef RT2870
2061 			NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6);
2062 			RT28XX_STA_ENTRY_MAC_RESET(pAd, i);
2063 #endif // RT2870 //
2064 
2065 			//AsicDelWcidTab(pAd, i);
2066 		}
2067 	}
2068 
2069 	return;
2070 }
2071 
2072 /*
2073 	==========================================================================
2074 	Description:
2075 
2076 	IRQL = DISPATCH_LEVEL
2077 
2078 	==========================================================================
2079 */
AssocParmFill(IN PRTMP_ADAPTER pAd,IN OUT MLME_ASSOC_REQ_STRUCT * AssocReq,IN PUCHAR pAddr,IN USHORT CapabilityInfo,IN ULONG Timeout,IN USHORT ListenIntv)2080 VOID AssocParmFill(
2081 	IN PRTMP_ADAPTER pAd,
2082 	IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
2083 	IN PUCHAR                     pAddr,
2084 	IN USHORT                     CapabilityInfo,
2085 	IN ULONG                      Timeout,
2086 	IN USHORT                     ListenIntv)
2087 {
2088 	COPY_MAC_ADDR(AssocReq->Addr, pAddr);
2089 	// Add mask to support 802.11b mode only
2090 	AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request
2091 	AssocReq->Timeout = Timeout;
2092 	AssocReq->ListenIntv = ListenIntv;
2093 }
2094 
2095 
2096 /*
2097 	==========================================================================
2098 	Description:
2099 
2100 	IRQL = DISPATCH_LEVEL
2101 
2102 	==========================================================================
2103 */
DisassocParmFill(IN PRTMP_ADAPTER pAd,IN OUT MLME_DISASSOC_REQ_STRUCT * DisassocReq,IN PUCHAR pAddr,IN USHORT Reason)2104 VOID DisassocParmFill(
2105 	IN PRTMP_ADAPTER pAd,
2106 	IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
2107 	IN PUCHAR pAddr,
2108 	IN USHORT Reason)
2109 {
2110 	COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
2111 	DisassocReq->Reason = Reason;
2112 }
2113 
2114 
2115 /*
2116 	========================================================================
2117 
2118 	Routine Description:
2119 		Check the out going frame, if this is an DHCP or ARP datagram
2120 	will be duplicate another frame at low data rate transmit.
2121 
2122 	Arguments:
2123 		pAd 		Pointer to our adapter
2124 		pPacket 	Pointer to outgoing Ndis frame
2125 
2126 	Return Value:
2127 		TRUE		To be duplicate at Low data rate transmit. (1mb)
2128 		FALSE		Do nothing.
2129 
2130 	IRQL = DISPATCH_LEVEL
2131 
2132 	Note:
2133 
2134 		MAC header + IP Header + UDP Header
2135 		  14 Bytes	  20 Bytes
2136 
2137 		UDP Header
2138 		00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
2139 						Source Port
2140 		16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
2141 					Destination Port
2142 
2143 		port 0x43 means Bootstrap Protocol, server.
2144 		Port 0x44 means Bootstrap Protocol, client.
2145 
2146 	========================================================================
2147 */
2148 
RTMPCheckDHCPFrame(IN PRTMP_ADAPTER pAd,IN PNDIS_PACKET pPacket)2149 BOOLEAN RTMPCheckDHCPFrame(
2150 	IN	PRTMP_ADAPTER	pAd,
2151 	IN	PNDIS_PACKET	pPacket)
2152 {
2153 	PACKET_INFO 	PacketInfo;
2154 	ULONG			NumberOfBytesRead = 0;
2155 	ULONG			CurrentOffset = 0;
2156 	PVOID			pVirtualAddress = NULL;
2157 	UINT			NdisBufferLength;
2158 	PUCHAR			pSrc;
2159 	USHORT			Protocol;
2160 	UCHAR			ByteOffset36 = 0;
2161 	UCHAR			ByteOffset38 = 0;
2162 	BOOLEAN 		ReadFirstParm = TRUE;
2163 
2164 	RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength);
2165 
2166 	NumberOfBytesRead += NdisBufferLength;
2167 	pSrc = (PUCHAR) pVirtualAddress;
2168 	Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
2169 
2170 	//
2171 	// Check DHCP & BOOTP protocol
2172 	//
2173 	while (NumberOfBytesRead <= PacketInfo.TotalPacketLength)
2174 	{
2175 		if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE))
2176 		{
2177 			CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength);
2178 			ByteOffset36 = *(pSrc + CurrentOffset);
2179 			ReadFirstParm = FALSE;
2180 		}
2181 
2182 		if (NumberOfBytesRead >= 37)
2183 		{
2184 			CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength);
2185 			ByteOffset38 = *(pSrc + CurrentOffset);
2186 			//End of Read
2187 			break;
2188 		}
2189 		return FALSE;
2190 	}
2191 
2192 	// Check for DHCP & BOOTP protocol
2193 	if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43))
2194 		{
2195 		//
2196 		// 2054 (hex 0806) for ARP datagrams
2197 		// if this packet is not ARP datagrams, then do nothing
2198 		// ARP datagrams will also be duplicate at 1mb broadcast frames
2199 		//
2200 		if (Protocol != 0x0806 )
2201 			return FALSE;
2202 		}
2203 
2204 	return TRUE;
2205 }
2206 
2207 
RTMPCheckEtherType(IN PRTMP_ADAPTER pAd,IN PNDIS_PACKET pPacket)2208 BOOLEAN RTMPCheckEtherType(
2209 	IN	PRTMP_ADAPTER	pAd,
2210 	IN	PNDIS_PACKET	pPacket)
2211 {
2212 	USHORT	TypeLen;
2213 	UCHAR	Byte0, Byte1;
2214 	PUCHAR	pSrcBuf;
2215 	UINT32	pktLen;
2216 	UINT16 	srcPort, dstPort;
2217 	BOOLEAN	status = TRUE;
2218 
2219 
2220 	pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
2221 	pktLen = GET_OS_PKT_LEN(pPacket);
2222 
2223 	ASSERT(pSrcBuf);
2224 
2225 	RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
2226 
2227 	// get Ethernet protocol field
2228 	TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13];
2229 
2230 	pSrcBuf += LENGTH_802_3;	// Skip the Ethernet Header.
2231 
2232 	if (TypeLen <= 1500)
2233 	{	// 802.3, 802.3 LLC
2234 		/*
2235 			DestMAC(6) + SrcMAC(6) + Lenght(2) +
2236 			DSAP(1) + SSAP(1) + Control(1) +
2237 			if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
2238 				=> + SNAP (5, OriginationID(3) + etherType(2))
2239 		*/
2240 		if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03)
2241 		{
2242 			Sniff2BytesFromNdisBuffer(pSrcBuf, 6, &Byte0, &Byte1);
2243 			RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
2244 			TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2245 			pSrcBuf += 8; // Skip this LLC/SNAP header
2246 		}
2247 		else
2248 		{
2249 			//It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.
2250 		}
2251 	}
2252 
2253 	// If it's a VLAN packet, get the real Type/Length field.
2254 	if (TypeLen == 0x8100)
2255 	{
2256 		/* 0x8100 means VLAN packets */
2257 
2258 		/* Dest. MAC Address (6-bytes) +
2259 		   Source MAC Address (6-bytes) +
2260 		   Length/Type = 802.1Q Tag Type (2-byte) +
2261 		   Tag Control Information (2-bytes) +
2262 		   Length / Type (2-bytes) +
2263 		   data payload (0-n bytes) +
2264 		   Pad (0-p bytes) +
2265 		   Frame Check Sequence (4-bytes) */
2266 
2267 		RTMP_SET_PACKET_VLAN(pPacket, 1);
2268 		Sniff2BytesFromNdisBuffer(pSrcBuf, 2, &Byte0, &Byte1);
2269 		TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2270 
2271 		pSrcBuf += 4; // Skip the VLAN Header.
2272 	}
2273 
2274 	switch (TypeLen)
2275 	{
2276 		case 0x0800:
2277 			{
2278 				ASSERT((pktLen > 34));
2279 				if (*(pSrcBuf + 9) == 0x11)
2280 				{	// udp packet
2281 					ASSERT((pktLen > 34));	// 14 for ethernet header, 20 for IP header
2282 
2283 					pSrcBuf += 20;	// Skip the IP header
2284 					srcPort = OS_NTOHS(*((UINT16 *)pSrcBuf));
2285 					dstPort = OS_NTOHS(*((UINT16 *)(pSrcBuf +2)));
2286 
2287 					if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44))
2288 					{	//It's a BOOTP/DHCP packet
2289 						RTMP_SET_PACKET_DHCP(pPacket, 1);
2290 					}
2291 				}
2292 			}
2293 			break;
2294 		case 0x0806:
2295 			{
2296 				//ARP Packet.
2297 				RTMP_SET_PACKET_DHCP(pPacket, 1);
2298 			}
2299 			break;
2300 		case 0x888e:
2301 			{
2302 				// EAPOL Packet.
2303 				RTMP_SET_PACKET_EAPOL(pPacket, 1);
2304 			}
2305 			break;
2306 		default:
2307 			status = FALSE;
2308 			break;
2309 	}
2310 
2311 	return status;
2312 
2313 }
2314 
2315 
2316 
Update_Rssi_Sample(IN PRTMP_ADAPTER pAd,IN RSSI_SAMPLE * pRssi,IN PRXWI_STRUC pRxWI)2317 VOID Update_Rssi_Sample(
2318 	IN PRTMP_ADAPTER	pAd,
2319 	IN RSSI_SAMPLE		*pRssi,
2320 	IN PRXWI_STRUC		pRxWI)
2321 		{
2322 	CHAR	rssi0 = pRxWI->RSSI0;
2323 	CHAR	rssi1 = pRxWI->RSSI1;
2324 	CHAR	rssi2 = pRxWI->RSSI2;
2325 
2326 	if (rssi0 != 0)
2327 	{
2328 		pRssi->LastRssi0	= ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0);
2329 		pRssi->AvgRssi0X8	= (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
2330 		pRssi->AvgRssi0	= pRssi->AvgRssi0X8 >> 3;
2331 	}
2332 
2333 	if (rssi1 != 0)
2334 	{
2335 		pRssi->LastRssi1	= ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1);
2336 		pRssi->AvgRssi1X8	= (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
2337 		pRssi->AvgRssi1	= pRssi->AvgRssi1X8 >> 3;
2338 	}
2339 
2340 	if (rssi2 != 0)
2341 	{
2342 		pRssi->LastRssi2	= ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2);
2343 		pRssi->AvgRssi2X8  = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
2344 		pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
2345 	}
2346 }
2347 
2348 
2349 
2350 // Normal legacy Rx packet indication
Indicate_Legacy_Packet(IN PRTMP_ADAPTER pAd,IN RX_BLK * pRxBlk,IN UCHAR FromWhichBSSID)2351 VOID Indicate_Legacy_Packet(
2352 	IN	PRTMP_ADAPTER	pAd,
2353 	IN	RX_BLK			*pRxBlk,
2354 	IN	UCHAR			FromWhichBSSID)
2355 {
2356 	PNDIS_PACKET	pRxPacket = pRxBlk->pRxPacket;
2357 	UCHAR			Header802_3[LENGTH_802_3];
2358 
2359 	// 1. get 802.3 Header
2360 	// 2. remove LLC
2361 	// 		a. pointer pRxBlk->pData to payload
2362 	//      b. modify pRxBlk->DataSize
2363 #ifdef CONFIG_STA_SUPPORT
2364 	IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2365 		RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2366 #endif // CONFIG_STA_SUPPORT //
2367 
2368 	if (pRxBlk->DataSize > MAX_RX_PKT_LEN)
2369 	{
2370 #if 0 // sample take off, for multiple card design
2371 		static int err_size;
2372 
2373 		err_size++;
2374 		if (err_size > 20)
2375 		{
2376 			 printk("Legacy DataSize = %d\n", pRxBlk->DataSize);
2377 			 hex_dump("802.3 Header", Header802_3, LENGTH_802_3);
2378 			 hex_dump("Payload", pRxBlk->pData, 64);
2379 			 err_size = 0;
2380 		}
2381 #endif
2382 
2383 		// release packet
2384 		RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2385 		return;
2386 	}
2387 
2388 
2389 	STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
2390 
2391 #ifdef RT2870
2392 #ifdef DOT11_N_SUPPORT
2393 	if (pAd->CommonCfg.bDisableReordering == 0)
2394 	{
2395 		PBA_REC_ENTRY		pBAEntry;
2396 		ULONG				Now32;
2397 		UCHAR				Wcid = pRxBlk->pRxWI->WirelessCliID;
2398 		UCHAR				TID = pRxBlk->pRxWI->TID;
2399 		USHORT				Idx;
2400 
2401 #define REORDERING_PACKET_TIMEOUT		((100 * HZ)/1000)	// system ticks -- 100 ms
2402 
2403 		if (Wcid < MAX_LEN_OF_MAC_TABLE)
2404 		{
2405 			Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
2406 			if (Idx != 0)
2407 			{
2408 				pBAEntry = &pAd->BATable.BARecEntry[Idx];
2409 				// update last rx time
2410 				NdisGetSystemUpTime(&Now32);
2411 				if ((pBAEntry->list.qlen > 0) &&
2412 					 RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
2413 	   				)
2414 				{
2415 					printk("Indicate_Legacy_Packet():flush reordering_timeout_mpdus! RxWI->Flags=%d, pRxWI.TID=%d, RxD->AMPDU=%d!\n", pRxBlk->Flags, pRxBlk->pRxWI->TID, pRxBlk->RxD.AMPDU);
2416 					hex_dump("Dump the legacy Packet:", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), 64);
2417 					ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
2418 				}
2419 			}
2420 		}
2421 	}
2422 #endif // DOT11_N_SUPPORT //
2423 #endif // RT2870 //
2424 
2425 	wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2426 
2427 	//
2428 	// pass this 802.3 packet to upper layer or forward this packet to WM directly
2429 	//
2430 #ifdef CONFIG_STA_SUPPORT
2431 	IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2432 		ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
2433 #endif // CONFIG_STA_SUPPORT //
2434 
2435 }
2436 
2437 
2438 // Normal, AMPDU or AMSDU
CmmRxnonRalinkFrameIndicate(IN PRTMP_ADAPTER pAd,IN RX_BLK * pRxBlk,IN UCHAR FromWhichBSSID)2439 VOID CmmRxnonRalinkFrameIndicate(
2440 	IN	PRTMP_ADAPTER	pAd,
2441 	IN	RX_BLK			*pRxBlk,
2442 	IN	UCHAR			FromWhichBSSID)
2443 {
2444 #ifdef DOT11_N_SUPPORT
2445 	if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
2446 	{
2447 		Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2448 	}
2449 	else
2450 #endif // DOT11_N_SUPPORT //
2451 	{
2452 #ifdef DOT11_N_SUPPORT
2453 		if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
2454 		{
2455 			// handle A-MSDU
2456 			Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2457 		}
2458 		else
2459 #endif // DOT11_N_SUPPORT //
2460 		{
2461 			Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
2462 		}
2463 	}
2464 }
2465 
2466 
CmmRxRalinkFrameIndicate(IN PRTMP_ADAPTER pAd,IN MAC_TABLE_ENTRY * pEntry,IN RX_BLK * pRxBlk,IN UCHAR FromWhichBSSID)2467 VOID CmmRxRalinkFrameIndicate(
2468 	IN	PRTMP_ADAPTER	pAd,
2469 	IN	MAC_TABLE_ENTRY	*pEntry,
2470 	IN	RX_BLK			*pRxBlk,
2471 	IN	UCHAR			FromWhichBSSID)
2472 {
2473 	UCHAR			Header802_3[LENGTH_802_3];
2474 	UINT16			Msdu2Size;
2475 	UINT16 			Payload1Size, Payload2Size;
2476 	PUCHAR 			pData2;
2477 	PNDIS_PACKET	pPacket2 = NULL;
2478 
2479 
2480 
2481 	Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8);
2482 
2483 	if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize))
2484 	{
2485 		/* skip two byte MSDU2 len */
2486 		pRxBlk->pData += 2;
2487 		pRxBlk->DataSize -= 2;
2488 	}
2489 	else
2490 	{
2491 		// release packet
2492 		RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2493 		return;
2494 	}
2495 
2496 	// get 802.3 Header and  remove LLC
2497 #ifdef CONFIG_STA_SUPPORT
2498 	IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2499 		RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2500 #endif // CONFIG_STA_SUPPORT //
2501 
2502 
2503 	ASSERT(pRxBlk->pRxPacket);
2504 
2505 	// Ralink Aggregation frame
2506 	pAd->RalinkCounters.OneSecRxAggregationCount ++;
2507 	Payload1Size = pRxBlk->DataSize - Msdu2Size;
2508 	Payload2Size = Msdu2Size - LENGTH_802_3;
2509 
2510 	pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
2511 #ifdef CONFIG_STA_SUPPORT
2512 	IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2513 		pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID);
2514 #endif // CONFIG_STA_SUPPORT //
2515 
2516 	if (!pPacket2)
2517 	{
2518 		// release packet
2519 		RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2520 		return;
2521 	}
2522 
2523 	// update payload size of 1st packet
2524 	pRxBlk->DataSize = Payload1Size;
2525 	wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2526 
2527 #ifdef CONFIG_STA_SUPPORT
2528 	IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2529 		ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID);
2530 #endif // CONFIG_STA_SUPPORT //
2531 
2532 	if (pPacket2)
2533 	{
2534 #ifdef CONFIG_STA_SUPPORT
2535 		IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2536 			ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
2537 #endif // CONFIG_STA_SUPPORT //
2538 	}
2539 }
2540 
2541 
2542 #define RESET_FRAGFRAME(_fragFrame) \
2543 	{								\
2544 		_fragFrame.RxSize = 0;		\
2545 		_fragFrame.Sequence = 0;	\
2546 		_fragFrame.LastFrag = 0;	\
2547 		_fragFrame.Flags = 0;		\
2548 	}
2549 
2550 
RTMPDeFragmentDataFrame(IN PRTMP_ADAPTER pAd,IN RX_BLK * pRxBlk)2551 PNDIS_PACKET RTMPDeFragmentDataFrame(
2552 	IN	PRTMP_ADAPTER	pAd,
2553 	IN	RX_BLK			*pRxBlk)
2554 {
2555 	PHEADER_802_11	pHeader = pRxBlk->pHeader;
2556 	PNDIS_PACKET	pRxPacket = pRxBlk->pRxPacket;
2557 	UCHAR			*pData = pRxBlk->pData;
2558 	USHORT			DataSize = pRxBlk->DataSize;
2559 	PNDIS_PACKET	pRetPacket = NULL;
2560 	UCHAR			*pFragBuffer = NULL;
2561 	BOOLEAN 		bReassDone = FALSE;
2562 	UCHAR			HeaderRoom = 0;
2563 
2564 
2565 	ASSERT(pHeader);
2566 
2567 	HeaderRoom = pData - (UCHAR *)pHeader;
2568 
2569 	// Re-assemble the fragmented packets
2570 	if (pHeader->Frag == 0)		// Frag. Number is 0 : First frag or only one pkt
2571 	{
2572 		// the first pkt of fragment, record it.
2573 		if (pHeader->FC.MoreFrag)
2574 		{
2575 			ASSERT(pAd->FragFrame.pFragPacket);
2576 			pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2577 			pAd->FragFrame.RxSize   = DataSize + HeaderRoom;
2578 			NdisMoveMemory(pFragBuffer,	 pHeader, pAd->FragFrame.RxSize);
2579 			pAd->FragFrame.Sequence = pHeader->Sequence;
2580 			pAd->FragFrame.LastFrag = pHeader->Frag;	   // Should be 0
2581 			ASSERT(pAd->FragFrame.LastFrag == 0);
2582 			goto done;	// end of processing this frame
2583 		}
2584 	}
2585 	else	//Middle & End of fragment
2586 	{
2587 		if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
2588 			(pHeader->Frag != (pAd->FragFrame.LastFrag + 1)))
2589 		{
2590 			// Fragment is not the same sequence or out of fragment number order
2591 			// Reset Fragment control blk
2592 			RESET_FRAGFRAME(pAd->FragFrame);
2593 			DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n"));
2594 			goto done; // give up this frame
2595 		}
2596 		else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE)
2597 		{
2598 			// Fragment frame is too large, it exeeds the maximum frame size.
2599 			// Reset Fragment control blk
2600 			RESET_FRAGFRAME(pAd->FragFrame);
2601 			DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
2602 			goto done; // give up this frame
2603 		}
2604 
2605         //
2606 		// Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.
2607 		// In this case, we will dropt it.
2608 		//
2609 		if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H)))
2610 		{
2611 			DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag));
2612 			goto done; // give up this frame
2613 		}
2614 
2615 		pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2616 
2617 		// concatenate this fragment into the re-assembly buffer
2618 		NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize);
2619 		pAd->FragFrame.RxSize  += DataSize;
2620 		pAd->FragFrame.LastFrag = pHeader->Frag;	   // Update fragment number
2621 
2622 		// Last fragment
2623 		if (pHeader->FC.MoreFrag == FALSE)
2624 		{
2625 			bReassDone = TRUE;
2626 		}
2627 	}
2628 
2629 done:
2630 	// always release rx fragmented packet
2631 	RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2632 
2633 	// return defragmented packet if packet is reassembled completely
2634 	// otherwise return NULL
2635 	if (bReassDone)
2636 	{
2637 		PNDIS_PACKET pNewFragPacket;
2638 
2639 		// allocate a new packet buffer for fragment
2640 		pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
2641 		if (pNewFragPacket)
2642 		{
2643 			// update RxBlk
2644 			pRetPacket = pAd->FragFrame.pFragPacket;
2645 			pAd->FragFrame.pFragPacket = pNewFragPacket;
2646 			pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
2647 			pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom;
2648 			pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
2649 			pRxBlk->pRxPacket = pRetPacket;
2650 		}
2651 		else
2652 		{
2653 			RESET_FRAGFRAME(pAd->FragFrame);
2654 		}
2655 	}
2656 
2657 	return pRetPacket;
2658 }
2659 
2660 
Indicate_AMSDU_Packet(IN PRTMP_ADAPTER pAd,IN RX_BLK * pRxBlk,IN UCHAR FromWhichBSSID)2661 VOID Indicate_AMSDU_Packet(
2662 	IN	PRTMP_ADAPTER	pAd,
2663 	IN	RX_BLK			*pRxBlk,
2664 	IN	UCHAR			FromWhichBSSID)
2665 {
2666 	UINT			nMSDU;
2667 
2668 	update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
2669 	RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
2670 	nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize);
2671 }
2672 
Indicate_EAPOL_Packet(IN PRTMP_ADAPTER pAd,IN RX_BLK * pRxBlk,IN UCHAR FromWhichBSSID)2673 VOID Indicate_EAPOL_Packet(
2674 	IN	PRTMP_ADAPTER	pAd,
2675 	IN	RX_BLK			*pRxBlk,
2676 	IN	UCHAR			FromWhichBSSID)
2677 {
2678 	MAC_TABLE_ENTRY *pEntry = NULL;
2679 
2680 
2681 #ifdef CONFIG_STA_SUPPORT
2682 	IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2683 	{
2684 		pEntry = &pAd->MacTab.Content[BSSID_WCID];
2685 		STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
2686 		return;
2687 	}
2688 #endif // CONFIG_STA_SUPPORT //
2689 
2690 	if (pEntry == NULL)
2691 	{
2692 		DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
2693 		// release packet
2694 		RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2695 		return;
2696 	}
2697 }
2698 
2699 #define BCN_TBTT_OFFSET		64	//defer 64 us
ReSyncBeaconTime(IN PRTMP_ADAPTER pAd)2700 VOID ReSyncBeaconTime(
2701 	IN  PRTMP_ADAPTER   pAd)
2702 {
2703 
2704 	UINT32  Offset;
2705 
2706 
2707 	Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
2708 
2709 	pAd->TbttTickCount++;
2710 
2711 	//
2712 	// The updated BeaconInterval Value will affect Beacon Interval after two TBTT
2713 	// beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
2714 	//
2715 	if (Offset == (BCN_TBTT_OFFSET-2))
2716 	{
2717 		BCN_TIME_CFG_STRUC csr;
2718 		RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2719 		csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ;	// ASIC register in units of 1/16 TU = 64us
2720 		RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2721 	}
2722 	else
2723 	{
2724 		if (Offset == (BCN_TBTT_OFFSET-1))
2725 		{
2726 			BCN_TIME_CFG_STRUC csr;
2727 
2728 			RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2729 			csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU
2730 			RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2731 		}
2732 	}
2733 }
2734 
2735