• 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/sta/
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	Module Name:
28	sync.c
29
30	Abstract:
31
32	Revision History:
33	Who			When			What
34	--------	----------		----------------------------------------------
35	John Chang	2004-09-01      modified for rt2561/2661
36	Jan Lee		2006-08-01      modified for rt2860 for 802.11n
37*/
38#include "../rt_config.h"
39
40#define ADHOC_ENTRY_BEACON_LOST_TIME	(2*OS_HZ)	/* 2 sec */
41
42/*
43	==========================================================================
44	Description:
45		The sync state machine,
46	Parameters:
47		Sm - pointer to the state machine
48	Note:
49		the state machine looks like the following
50
51	==========================================================================
52 */
53void SyncStateMachineInit(struct rt_rtmp_adapter *pAd,
54			  struct rt_state_machine *Sm, OUT STATE_MACHINE_FUNC Trans[])
55{
56	StateMachineInit(Sm, Trans, MAX_SYNC_STATE, MAX_SYNC_MSG,
57			 (STATE_MACHINE_FUNC) Drop, SYNC_IDLE,
58			 SYNC_MACHINE_BASE);
59
60	/* column 1 */
61	StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_SCAN_REQ,
62			      (STATE_MACHINE_FUNC) MlmeScanReqAction);
63	StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_JOIN_REQ,
64			      (STATE_MACHINE_FUNC) MlmeJoinReqAction);
65	StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_START_REQ,
66			      (STATE_MACHINE_FUNC) MlmeStartReqAction);
67	StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_BEACON,
68			      (STATE_MACHINE_FUNC) PeerBeacon);
69	StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_PROBE_REQ,
70			      (STATE_MACHINE_FUNC) PeerProbeReqAction);
71
72	/*column 2 */
73	StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_SCAN_REQ,
74			      (STATE_MACHINE_FUNC) InvalidStateWhenScan);
75	StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_JOIN_REQ,
76			      (STATE_MACHINE_FUNC) InvalidStateWhenJoin);
77	StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_START_REQ,
78			      (STATE_MACHINE_FUNC) InvalidStateWhenStart);
79	StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_PEER_BEACON,
80			      (STATE_MACHINE_FUNC) PeerBeaconAtJoinAction);
81	StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_BEACON_TIMEOUT,
82			      (STATE_MACHINE_FUNC) BeaconTimeoutAtJoinAction);
83
84	/* column 3 */
85	StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_SCAN_REQ,
86			      (STATE_MACHINE_FUNC) InvalidStateWhenScan);
87	StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_JOIN_REQ,
88			      (STATE_MACHINE_FUNC) InvalidStateWhenJoin);
89	StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_START_REQ,
90			      (STATE_MACHINE_FUNC) InvalidStateWhenStart);
91	StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_BEACON,
92			      (STATE_MACHINE_FUNC) PeerBeaconAtScanAction);
93	StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_PROBE_RSP,
94			      (STATE_MACHINE_FUNC) PeerBeaconAtScanAction);
95	StateMachineSetAction(Sm, SCAN_LISTEN, MT2_SCAN_TIMEOUT,
96			      (STATE_MACHINE_FUNC) ScanTimeoutAction);
97
98	/* timer init */
99	RTMPInitTimer(pAd, &pAd->MlmeAux.BeaconTimer,
100		      GET_TIMER_FUNCTION(BeaconTimeout), pAd, FALSE);
101	RTMPInitTimer(pAd, &pAd->MlmeAux.ScanTimer,
102		      GET_TIMER_FUNCTION(ScanTimeout), pAd, FALSE);
103}
104
105/*
106	==========================================================================
107	Description:
108		Beacon timeout handler, executed in timer thread
109
110	IRQL = DISPATCH_LEVEL
111
112	==========================================================================
113 */
114void BeaconTimeout(void *SystemSpecific1,
115		   void *FunctionContext,
116		   void *SystemSpecific2, void *SystemSpecific3)
117{
118	struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
119
120	DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BeaconTimeout\n"));
121
122	/* Do nothing if the driver is starting halt state. */
123	/* This might happen when timer already been fired before cancel timer with mlmehalt */
124	if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
125		return;
126
127	if ((pAd->CommonCfg.BBPCurrentBW == BW_40)
128	    ) {
129		u8 BBPValue = 0;
130		AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
131		AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
132		RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
133		BBPValue &= (~0x18);
134		BBPValue |= 0x10;
135		RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
136		DBGPRINT(RT_DEBUG_TRACE,
137			 ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n",
138			  pAd->CommonCfg.CentralChannel, pAd->ScanTab.BssNr));
139	}
140
141	MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_BEACON_TIMEOUT, 0, NULL);
142	RTMP_MLME_HANDLER(pAd);
143}
144
145/*
146	==========================================================================
147	Description:
148		Scan timeout handler, executed in timer thread
149
150	IRQL = DISPATCH_LEVEL
151
152	==========================================================================
153 */
154void ScanTimeout(void *SystemSpecific1,
155		 void *FunctionContext,
156		 void *SystemSpecific2, void *SystemSpecific3)
157{
158	struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
159
160	/* Do nothing if the driver is starting halt state. */
161	/* This might happen when timer already been fired before cancel timer with mlmehalt */
162	if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
163		return;
164
165	if (MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_SCAN_TIMEOUT, 0, NULL)) {
166		RTMP_MLME_HANDLER(pAd);
167	} else {
168		/* To prevent SyncMachine.CurrState is SCAN_LISTEN forever. */
169		pAd->MlmeAux.Channel = 0;
170		ScanNextChannel(pAd);
171		if (pAd->CommonCfg.bWirelessEvent) {
172			RTMPSendWirelessEvent(pAd,
173					      IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG,
174					      pAd->MacTab.Content[BSSID_WCID].
175					      Addr, BSS0, 0);
176		}
177	}
178}
179
180/*
181	==========================================================================
182	Description:
183		MLME SCAN req state machine procedure
184	==========================================================================
185 */
186void MlmeScanReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
187{
188	u8 Ssid[MAX_LEN_OF_SSID], SsidLen, ScanType, BssType, BBPValue = 0;
189	BOOLEAN TimerCancelled;
190	unsigned long Now;
191	u16 Status;
192	struct rt_header_802_11 * pHdr80211;
193	u8 *pOutBuffer = NULL;
194	int NStatus;
195
196	/* Check the total scan tries for one single OID command */
197	/* If this is the CCX 2.0 Case, skip that! */
198	if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) {
199		DBGPRINT(RT_DEBUG_TRACE,
200			 ("SYNC - MlmeScanReqAction before Startup\n"));
201		return;
202	}
203	/* Increase the scan retry counters. */
204	pAd->StaCfg.ScanCnt++;
205
206#ifdef RTMP_MAC_PCI
207	if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) &&
208	    (IDLE_ON(pAd)) &&
209	    (pAd->StaCfg.bRadio == TRUE) &&
210	    (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) {
211		if (pAd->StaCfg.PSControl.field.EnableNewPS == FALSE) {
212			AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00,
213					     0x02);
214			AsicCheckCommanOk(pAd, PowerWakeCID);
215			RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
216			DBGPRINT(RT_DEBUG_TRACE,
217				 ("PSM - Issue Wake up command \n"));
218		} else {
219			RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE);
220		}
221	}
222#endif /* RTMP_MAC_PCI // */
223
224	/* first check the parameter sanity */
225	if (MlmeScanReqSanity(pAd,
226			      Elem->Msg,
227			      Elem->MsgLen,
228			      &BssType, (char *)Ssid, &SsidLen, &ScanType)) {
229
230		/* Check for channel load and noise hist request */
231		/* Suspend MSDU only at scan request, not the last two mentioned */
232		/* Suspend MSDU transmission here */
233		RTMPSuspendMsduTransmission(pAd);
234
235		/* */
236		/* To prevent data lost. */
237		/* Send an NULL data with turned PSM bit on to current associated AP before SCAN progress. */
238		/* And should send an NULL data with turned PSM bit off to AP, when scan progress done */
239		/* */
240		if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
241		    && (INFRA_ON(pAd))) {
242			NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer);
243			if (NStatus == NDIS_STATUS_SUCCESS) {
244				pHdr80211 = (struct rt_header_802_11 *) pOutBuffer;
245				MgtMacHeaderInit(pAd, pHdr80211,
246						 SUBTYPE_NULL_FUNC, 1,
247						 pAd->CommonCfg.Bssid,
248						 pAd->CommonCfg.Bssid);
249				pHdr80211->Duration = 0;
250				pHdr80211->FC.Type = BTYPE_DATA;
251				pHdr80211->FC.PwrMgmt = PWR_SAVE;
252
253				/* Send using priority queue */
254				MiniportMMRequest(pAd, 0, pOutBuffer,
255						  sizeof(struct rt_header_802_11));
256				DBGPRINT(RT_DEBUG_TRACE,
257					 ("MlmeScanReqAction -- Send PSM Data frame for off channel RM\n"));
258				MlmeFreeMemory(pAd, pOutBuffer);
259				RTMPusecDelay(5000);
260			}
261		}
262
263		NdisGetSystemUpTime(&Now);
264		pAd->StaCfg.LastScanTime = Now;
265		/* reset all the timers */
266		RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
267		RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled);
268
269		/* record desired BSS parameters */
270		pAd->MlmeAux.BssType = BssType;
271		pAd->MlmeAux.ScanType = ScanType;
272		pAd->MlmeAux.SsidLen = SsidLen;
273		NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID);
274		NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen);
275
276		/* start from the first channel */
277		pAd->MlmeAux.Channel = FirstChannel(pAd);
278
279		/* Let BBP register at 20MHz to do scan */
280		RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
281		BBPValue &= (~0x18);
282		RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
283		DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n"));
284		ScanNextChannel(pAd);
285	} else {
286		DBGPRINT_ERR(("SYNC - MlmeScanReqAction() sanity check fail\n"));
287		pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
288		Status = MLME_INVALID_FORMAT;
289		MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2,
290			    &Status);
291	}
292}
293
294/*
295	==========================================================================
296	Description:
297		MLME JOIN req state machine procedure
298	==========================================================================
299 */
300void MlmeJoinReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
301{
302	u8 BBPValue = 0;
303	struct rt_bss_entry *pBss;
304	BOOLEAN TimerCancelled;
305	struct rt_header_802_11 Hdr80211;
306	int NStatus;
307	unsigned long FrameLen = 0;
308	u8 *pOutBuffer = NULL;
309	u8 *pSupRate = NULL;
310	u8 SupRateLen;
311	u8 *pExtRate = NULL;
312	u8 ExtRateLen;
313	u8 ASupRate[] = { 0x8C, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6C };
314	u8 ASupRateLen = sizeof(ASupRate) / sizeof(u8);
315	struct rt_mlme_join_req *pInfo = (struct rt_mlme_join_req *)(Elem->Msg);
316
317	DBGPRINT(RT_DEBUG_TRACE,
318		 ("SYNC - MlmeJoinReqAction(BSS #%ld)\n", pInfo->BssIdx));
319
320#ifdef RTMP_MAC_PCI
321	if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) &&
322	    (IDLE_ON(pAd)) &&
323	    (pAd->StaCfg.bRadio == TRUE) &&
324	    (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) {
325		RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE);
326	}
327#endif /* RTMP_MAC_PCI // */
328
329	/* reset all the timers */
330	RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled);
331	RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
332
333	pBss = &pAd->MlmeAux.SsidBssTab.BssEntry[pInfo->BssIdx];
334
335	/* record the desired SSID & BSSID we're waiting for */
336	COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pBss->Bssid);
337
338	/* If AP's SSID is not hidden, it is OK for updating ssid to MlmeAux again. */
339	if (pBss->Hidden == 0) {
340		RTMPZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID);
341		NdisMoveMemory(pAd->MlmeAux.Ssid, pBss->Ssid, pBss->SsidLen);
342		pAd->MlmeAux.SsidLen = pBss->SsidLen;
343	}
344
345	pAd->MlmeAux.BssType = pBss->BssType;
346	pAd->MlmeAux.Channel = pBss->Channel;
347	pAd->MlmeAux.CentralChannel = pBss->CentralChannel;
348
349	/* Let BBP register at 20MHz to do scan */
350	RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
351	BBPValue &= (~0x18);
352	RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
353
354	DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n"));
355
356	/* switch channel and waiting for beacon timer */
357	AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE);
358	AsicLockChannel(pAd, pAd->MlmeAux.Channel);
359	RTMPSetTimer(&pAd->MlmeAux.BeaconTimer, JOIN_TIMEOUT);
360
361	do {
362		if (((pAd->CommonCfg.bIEEE80211H == 1) &&
363		     (pAd->MlmeAux.Channel > 14) &&
364		     RadarChannelCheck(pAd, pAd->MlmeAux.Channel))
365		    ) {
366			/* */
367			/* We can't send any Probe request frame to meet 802.11h. */
368			/* */
369			if (pBss->Hidden == 0)
370				break;
371		}
372		/* */
373		/* send probe request */
374		/* */
375		NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
376		if (NStatus == NDIS_STATUS_SUCCESS) {
377			if (pAd->MlmeAux.Channel <= 14) {
378				pSupRate = pAd->CommonCfg.SupRate;
379				SupRateLen = pAd->CommonCfg.SupRateLen;
380				pExtRate = pAd->CommonCfg.ExtRate;
381				ExtRateLen = pAd->CommonCfg.ExtRateLen;
382			} else {
383				/* */
384				/* Overwrite Support Rate, CCK rate are not allowed */
385				/* */
386				pSupRate = ASupRate;
387				SupRateLen = ASupRateLen;
388				ExtRateLen = 0;
389			}
390
391			if (pAd->MlmeAux.BssType == BSS_INFRA)
392				MgtMacHeaderInit(pAd, &Hdr80211,
393						 SUBTYPE_PROBE_REQ, 0,
394						 pAd->MlmeAux.Bssid,
395						 pAd->MlmeAux.Bssid);
396			else
397				MgtMacHeaderInit(pAd, &Hdr80211,
398						 SUBTYPE_PROBE_REQ, 0,
399						 BROADCAST_ADDR,
400						 BROADCAST_ADDR);
401
402			MakeOutgoingFrame(pOutBuffer, &FrameLen,
403					  sizeof(struct rt_header_802_11), &Hdr80211,
404					  1, &SsidIe,
405					  1, &pAd->MlmeAux.SsidLen,
406					  pAd->MlmeAux.SsidLen,
407					  pAd->MlmeAux.Ssid, 1, &SupRateIe, 1,
408					  &SupRateLen, SupRateLen, pSupRate,
409					  END_OF_ARGS);
410
411			if (ExtRateLen) {
412				unsigned long Tmp;
413				MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp,
414						  1, &ExtRateIe,
415						  1, &ExtRateLen,
416						  ExtRateLen, pExtRate,
417						  END_OF_ARGS);
418				FrameLen += Tmp;
419			}
420
421			MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
422			MlmeFreeMemory(pAd, pOutBuffer);
423		}
424	} while (FALSE);
425
426	DBGPRINT(RT_DEBUG_TRACE,
427		 ("SYNC - Switch to ch %d, Wait BEACON from %02x:%02x:%02x:%02x:%02x:%02x\n",
428		  pBss->Channel, pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2],
429		  pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5]));
430
431	pAd->Mlme.SyncMachine.CurrState = JOIN_WAIT_BEACON;
432}
433
434/*
435	==========================================================================
436	Description:
437		MLME START Request state machine procedure, starting an IBSS
438	==========================================================================
439 */
440void MlmeStartReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
441{
442	u8 Ssid[MAX_LEN_OF_SSID], SsidLen;
443	BOOLEAN TimerCancelled;
444
445	/* New for WPA security suites */
446	u8 VarIE[MAX_VIE_LEN];	/* Total VIE length = MAX_VIE_LEN - -5 */
447	struct rt_ndis_802_11_variable_ies *pVIE = NULL;
448	LARGE_INTEGER TimeStamp;
449	BOOLEAN Privacy;
450	u16 Status;
451
452	/* Init Variable IE structure */
453	pVIE = (struct rt_ndis_802_11_variable_ies *)VarIE;
454	pVIE->Length = 0;
455	TimeStamp.u.LowPart = 0;
456	TimeStamp.u.HighPart = 0;
457
458	if (MlmeStartReqSanity
459	    (pAd, Elem->Msg, Elem->MsgLen, (char *)Ssid, &SsidLen)) {
460		/* reset all the timers */
461		RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled);
462		RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
463
464		/* */
465		/* Start a new IBSS. All IBSS parameters are decided now.... */
466		/* */
467		DBGPRINT(RT_DEBUG_TRACE,
468			 ("MlmeStartReqAction - Start a new IBSS. All IBSS parameters are decided now.... \n"));
469		pAd->MlmeAux.BssType = BSS_ADHOC;
470		NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen);
471		pAd->MlmeAux.SsidLen = SsidLen;
472
473		/* generate a radom number as BSSID */
474		MacAddrRandomBssid(pAd, pAd->MlmeAux.Bssid);
475		DBGPRINT(RT_DEBUG_TRACE,
476			 ("MlmeStartReqAction - generate a radom number as BSSID \n"));
477
478		Privacy =
479		    (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled)
480		    || (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled)
481		    || (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled);
482		pAd->MlmeAux.CapabilityInfo =
483		    CAP_GENERATE(0, 1, Privacy,
484				 (pAd->CommonCfg.TxPreamble ==
485				  Rt802_11PreambleShort), 1, 0);
486		pAd->MlmeAux.BeaconPeriod = pAd->CommonCfg.BeaconPeriod;
487		pAd->MlmeAux.AtimWin = pAd->StaCfg.AtimWin;
488		pAd->MlmeAux.Channel = pAd->CommonCfg.Channel;
489
490		pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel;
491		pAd->MlmeAux.CentralChannel = pAd->CommonCfg.CentralChannel;
492
493		pAd->MlmeAux.SupRateLen = pAd->CommonCfg.SupRateLen;
494		NdisMoveMemory(pAd->MlmeAux.SupRate, pAd->CommonCfg.SupRate,
495			       MAX_LEN_OF_SUPPORTED_RATES);
496		RTMPCheckRates(pAd, pAd->MlmeAux.SupRate,
497			       &pAd->MlmeAux.SupRateLen);
498		pAd->MlmeAux.ExtRateLen = pAd->CommonCfg.ExtRateLen;
499		NdisMoveMemory(pAd->MlmeAux.ExtRate, pAd->CommonCfg.ExtRate,
500			       MAX_LEN_OF_SUPPORTED_RATES);
501		RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate,
502			       &pAd->MlmeAux.ExtRateLen);
503
504		if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) {
505			RTMPUpdateHTIE(&pAd->CommonCfg.DesiredHtPhy,
506				       &pAd->StaCfg.DesiredHtPhyInfo.MCSSet[0],
507				       &pAd->MlmeAux.HtCapability,
508				       &pAd->MlmeAux.AddHtInfo);
509			pAd->MlmeAux.HtCapabilityLen = sizeof(struct rt_ht_capability_ie);
510			/* Not turn pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE here. */
511			DBGPRINT(RT_DEBUG_TRACE,
512				 ("SYNC -pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE\n"));
513		} else {
514			pAd->MlmeAux.HtCapabilityLen = 0;
515			pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE;
516			NdisZeroMemory(&pAd->StaActive.SupportedPhyInfo.
517				       MCSSet[0], 16);
518		}
519		/* temporarily not support QOS in IBSS */
520		NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(struct rt_edca_parm));
521		NdisZeroMemory(&pAd->MlmeAux.APQbssLoad,
522			       sizeof(struct rt_qbss_load_parm));
523		NdisZeroMemory(&pAd->MlmeAux.APQosCapability,
524			       sizeof(struct rt_qos_capability_parm));
525
526		AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE);
527		AsicLockChannel(pAd, pAd->MlmeAux.Channel);
528
529		DBGPRINT(RT_DEBUG_TRACE,
530			 ("SYNC - MlmeStartReqAction(ch= %d,sup rates= %d, ext rates=%d)\n",
531			  pAd->MlmeAux.Channel, pAd->MlmeAux.SupRateLen,
532			  pAd->MlmeAux.ExtRateLen));
533
534		pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
535		Status = MLME_SUCCESS;
536		MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2,
537			    &Status);
538	} else {
539		DBGPRINT_ERR(("SYNC - MlmeStartReqAction() sanity check fail.\n"));
540		pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
541		Status = MLME_INVALID_FORMAT;
542		MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2,
543			    &Status);
544	}
545}
546
547/*
548	==========================================================================
549	Description:
550		peer sends beacon back when scanning
551	==========================================================================
552 */
553void PeerBeaconAtScanAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
554{
555	u8 Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN];
556	u8 Ssid[MAX_LEN_OF_SSID], BssType, Channel, NewChannel,
557	    SsidLen, DtimCount, DtimPeriod, BcastFlag, MessageToMe;
558	struct rt_cf_parm CfParm;
559	u16 BeaconPeriod, AtimWin, CapabilityInfo;
560	struct rt_frame_802_11 * pFrame;
561	LARGE_INTEGER TimeStamp;
562	u8 Erp;
563	u8 SupRate[MAX_LEN_OF_SUPPORTED_RATES],
564	    ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
565	u8 SupRateLen, ExtRateLen;
566	u16 LenVIE;
567	u8 CkipFlag;
568	u8 AironetCellPowerLimit;
569	struct rt_edca_parm EdcaParm;
570	struct rt_qbss_load_parm QbssLoad;
571	struct rt_qos_capability_parm QosCapability;
572	unsigned long RalinkIe;
573	u8 VarIE[MAX_VIE_LEN];	/* Total VIE length = MAX_VIE_LEN - -5 */
574	struct rt_ndis_802_11_variable_ies *pVIE = NULL;
575	struct rt_ht_capability_ie HtCapability;
576	struct rt_add_ht_info_ie AddHtInfo;	/* AP might use this additional ht info IE */
577	u8 HtCapabilityLen = 0, PreNHtCapabilityLen = 0;
578	u8 AddHtInfoLen;
579	u8 NewExtChannelOffset = 0xff;
580
581	/* NdisFillMemory(Ssid, MAX_LEN_OF_SSID, 0x00); */
582	pFrame = (struct rt_frame_802_11 *) Elem->Msg;
583	/* Init Variable IE structure */
584	pVIE = (struct rt_ndis_802_11_variable_ies *)VarIE;
585	pVIE->Length = 0;
586
587	RTMPZeroMemory(&HtCapability, sizeof(HtCapability));
588	RTMPZeroMemory(&AddHtInfo, sizeof(struct rt_add_ht_info_ie));
589
590	if (PeerBeaconAndProbeRspSanity(pAd,
591					Elem->Msg,
592					Elem->MsgLen,
593					Elem->Channel,
594					Addr2,
595					Bssid,
596					(char *)Ssid,
597					&SsidLen,
598					&BssType,
599					&BeaconPeriod,
600					&Channel,
601					&NewChannel,
602					&TimeStamp,
603					&CfParm,
604					&AtimWin,
605					&CapabilityInfo,
606					&Erp,
607					&DtimCount,
608					&DtimPeriod,
609					&BcastFlag,
610					&MessageToMe,
611					SupRate,
612					&SupRateLen,
613					ExtRate,
614					&ExtRateLen,
615					&CkipFlag,
616					&AironetCellPowerLimit,
617					&EdcaParm,
618					&QbssLoad,
619					&QosCapability,
620					&RalinkIe,
621					&HtCapabilityLen,
622					&PreNHtCapabilityLen,
623					&HtCapability,
624					&AddHtInfoLen,
625					&AddHtInfo,
626					&NewExtChannelOffset, &LenVIE, pVIE)) {
627		unsigned long Idx;
628		char Rssi = 0;
629
630		Idx = BssTableSearch(&pAd->ScanTab, Bssid, Channel);
631		if (Idx != BSS_NOT_FOUND)
632			Rssi = pAd->ScanTab.BssEntry[Idx].Rssi;
633
634		Rssi =
635		    RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0),
636				ConvertToRssi(pAd, Elem->Rssi1, RSSI_1),
637				ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
638
639		if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0))
640			HtCapabilityLen = SIZE_HT_CAP_IE;
641
642		Idx =
643		    BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, (char *)Ssid,
644				     SsidLen, BssType, BeaconPeriod, &CfParm,
645				     AtimWin, CapabilityInfo, SupRate,
646				     SupRateLen, ExtRate, ExtRateLen,
647				     &HtCapability, &AddHtInfo, HtCapabilityLen,
648				     AddHtInfoLen, NewExtChannelOffset, Channel,
649				     Rssi, TimeStamp, CkipFlag, &EdcaParm,
650				     &QosCapability, &QbssLoad, LenVIE, pVIE);
651
652		if (Idx != BSS_NOT_FOUND) {
653			NdisMoveMemory(pAd->ScanTab.BssEntry[Idx].PTSF,
654				       &Elem->Msg[24], 4);
655			NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[0],
656				       &Elem->TimeStamp.u.LowPart, 4);
657			NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[4],
658				       &Elem->TimeStamp.u.LowPart, 4);
659		}
660
661	}
662	/* sanity check fail, ignored */
663}
664
665/*
666	==========================================================================
667	Description:
668		When waiting joining the (I)BSS, beacon received from external
669	==========================================================================
670 */
671void PeerBeaconAtJoinAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
672{
673	u8 Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN];
674	u8 Ssid[MAX_LEN_OF_SSID], SsidLen, BssType, Channel, MessageToMe,
675	    DtimCount, DtimPeriod, BcastFlag, NewChannel;
676	LARGE_INTEGER TimeStamp;
677	u16 BeaconPeriod, AtimWin, CapabilityInfo;
678	struct rt_cf_parm Cf;
679	BOOLEAN TimerCancelled;
680	u8 Erp;
681	u8 SupRate[MAX_LEN_OF_SUPPORTED_RATES],
682	    ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
683	u8 SupRateLen, ExtRateLen;
684	u8 CkipFlag;
685	u16 LenVIE;
686	u8 AironetCellPowerLimit;
687	struct rt_edca_parm EdcaParm;
688	struct rt_qbss_load_parm QbssLoad;
689	struct rt_qos_capability_parm QosCapability;
690	u16 Status;
691	u8 VarIE[MAX_VIE_LEN];	/* Total VIE length = MAX_VIE_LEN - -5 */
692	struct rt_ndis_802_11_variable_ies *pVIE = NULL;
693	unsigned long RalinkIe;
694	unsigned long Idx;
695	struct rt_ht_capability_ie HtCapability;
696	struct rt_add_ht_info_ie AddHtInfo;	/* AP might use this additional ht info IE */
697	u8 HtCapabilityLen = 0, PreNHtCapabilityLen = 0;
698	u8 AddHtInfoLen;
699	u8 NewExtChannelOffset = 0xff;
700	u8 CentralChannel;
701	BOOLEAN bAllowNrate = FALSE;
702
703	/* Init Variable IE structure */
704	pVIE = (struct rt_ndis_802_11_variable_ies *)VarIE;
705	pVIE->Length = 0;
706	RTMPZeroMemory(&HtCapability, sizeof(HtCapability));
707	RTMPZeroMemory(&AddHtInfo, sizeof(struct rt_add_ht_info_ie));
708
709	if (PeerBeaconAndProbeRspSanity(pAd,
710					Elem->Msg,
711					Elem->MsgLen,
712					Elem->Channel,
713					Addr2,
714					Bssid,
715					(char *)Ssid,
716					&SsidLen,
717					&BssType,
718					&BeaconPeriod,
719					&Channel,
720					&NewChannel,
721					&TimeStamp,
722					&Cf,
723					&AtimWin,
724					&CapabilityInfo,
725					&Erp,
726					&DtimCount,
727					&DtimPeriod,
728					&BcastFlag,
729					&MessageToMe,
730					SupRate,
731					&SupRateLen,
732					ExtRate,
733					&ExtRateLen,
734					&CkipFlag,
735					&AironetCellPowerLimit,
736					&EdcaParm,
737					&QbssLoad,
738					&QosCapability,
739					&RalinkIe,
740					&HtCapabilityLen,
741					&PreNHtCapabilityLen,
742					&HtCapability,
743					&AddHtInfoLen,
744					&AddHtInfo,
745					&NewExtChannelOffset, &LenVIE, pVIE)) {
746		/* Disqualify 11b only adhoc when we are in 11g only adhoc mode */
747		if ((BssType == BSS_ADHOC)
748		    && (pAd->CommonCfg.PhyMode == PHY_11G)
749		    && ((SupRateLen + ExtRateLen) < 12))
750			return;
751
752		/* BEACON from desired BSS/IBSS found. We should be able to decide most */
753		/* BSS parameters here. */
754		/* Q. But what happen if this JOIN doesn't conclude a successful ASSOCIATEION? */
755		/*    Do we need to receover back all parameters belonging to previous BSS? */
756		/* A. Should be not. There's no back-door recover to previous AP. It still need */
757		/*    a new JOIN-AUTH-ASSOC sequence. */
758		if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Bssid)) {
759			DBGPRINT(RT_DEBUG_TRACE,
760				 ("SYNC - receive desired BEACON at JoinWaitBeacon... Channel = %d\n",
761				  Channel));
762			RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer,
763					&TimerCancelled);
764
765			/* Update RSSI to prevent No signal display when cards first initialized */
766			pAd->StaCfg.RssiSample.LastRssi0 =
767			    ConvertToRssi(pAd, Elem->Rssi0, RSSI_0);
768			pAd->StaCfg.RssiSample.LastRssi1 =
769			    ConvertToRssi(pAd, Elem->Rssi1, RSSI_1);
770			pAd->StaCfg.RssiSample.LastRssi2 =
771			    ConvertToRssi(pAd, Elem->Rssi2, RSSI_2);
772			pAd->StaCfg.RssiSample.AvgRssi0 =
773			    pAd->StaCfg.RssiSample.LastRssi0;
774			pAd->StaCfg.RssiSample.AvgRssi0X8 =
775			    pAd->StaCfg.RssiSample.AvgRssi0 << 3;
776			pAd->StaCfg.RssiSample.AvgRssi1 =
777			    pAd->StaCfg.RssiSample.LastRssi1;
778			pAd->StaCfg.RssiSample.AvgRssi1X8 =
779			    pAd->StaCfg.RssiSample.AvgRssi1 << 3;
780			pAd->StaCfg.RssiSample.AvgRssi2 =
781			    pAd->StaCfg.RssiSample.LastRssi2;
782			pAd->StaCfg.RssiSample.AvgRssi2X8 =
783			    pAd->StaCfg.RssiSample.AvgRssi2 << 3;
784
785			/* */
786			/* We need to check if SSID only set to any, then we can record the current SSID. */
787			/* Otherwise will cause hidden SSID association failed. */
788			/* */
789			if (pAd->MlmeAux.SsidLen == 0) {
790				NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid,
791					       SsidLen);
792				pAd->MlmeAux.SsidLen = SsidLen;
793			} else {
794				Idx =
795				    BssSsidTableSearch(&pAd->ScanTab, Bssid,
796						       pAd->MlmeAux.Ssid,
797						       pAd->MlmeAux.SsidLen,
798						       Channel);
799
800				if (Idx == BSS_NOT_FOUND) {
801					char Rssi = 0;
802					Rssi =
803					    RTMPMaxRssi(pAd,
804							ConvertToRssi(pAd,
805								      Elem->
806								      Rssi0,
807								      RSSI_0),
808							ConvertToRssi(pAd,
809								      Elem->
810								      Rssi1,
811								      RSSI_1),
812							ConvertToRssi(pAd,
813								      Elem->
814								      Rssi2,
815								      RSSI_2));
816					Idx =
817					    BssTableSetEntry(pAd, &pAd->ScanTab,
818							     Bssid,
819							     (char *) Ssid,
820							     SsidLen, BssType,
821							     BeaconPeriod, &Cf,
822							     AtimWin,
823							     CapabilityInfo,
824							     SupRate,
825							     SupRateLen,
826							     ExtRate,
827							     ExtRateLen,
828							     &HtCapability,
829							     &AddHtInfo,
830							     HtCapabilityLen,
831							     AddHtInfoLen,
832							     NewExtChannelOffset,
833							     Channel, Rssi,
834							     TimeStamp,
835							     CkipFlag,
836							     &EdcaParm,
837							     &QosCapability,
838							     &QbssLoad, LenVIE,
839							     pVIE);
840					if (Idx != BSS_NOT_FOUND) {
841						NdisMoveMemory(pAd->ScanTab.
842							       BssEntry[Idx].
843							       PTSF,
844							       &Elem->Msg[24],
845							       4);
846						NdisMoveMemory(&pAd->ScanTab.
847							       BssEntry[Idx].
848							       TTSF[0],
849							       &Elem->TimeStamp.
850							       u.LowPart, 4);
851						NdisMoveMemory(&pAd->ScanTab.
852							       BssEntry[Idx].
853							       TTSF[4],
854							       &Elem->TimeStamp.
855							       u.LowPart, 4);
856						CapabilityInfo =
857						    pAd->ScanTab.BssEntry[Idx].
858						    CapabilityInfo;
859					}
860				} else {
861					/* */
862					/* Multiple SSID case, used correct CapabilityInfo */
863					/* */
864					CapabilityInfo =
865					    pAd->ScanTab.BssEntry[Idx].
866					    CapabilityInfo;
867				}
868			}
869			NdisMoveMemory(pAd->MlmeAux.Bssid, Bssid, MAC_ADDR_LEN);
870			pAd->MlmeAux.CapabilityInfo =
871			    CapabilityInfo & SUPPORTED_CAPABILITY_INFO;
872			pAd->MlmeAux.BssType = BssType;
873			pAd->MlmeAux.BeaconPeriod = BeaconPeriod;
874			pAd->MlmeAux.Channel = Channel;
875			pAd->MlmeAux.AtimWin = AtimWin;
876			pAd->MlmeAux.CfpPeriod = Cf.CfpPeriod;
877			pAd->MlmeAux.CfpMaxDuration = Cf.CfpMaxDuration;
878			pAd->MlmeAux.APRalinkIe = RalinkIe;
879
880			/* Copy AP's supported rate to MlmeAux for creating assoication request */
881			/* Also filter out not supported rate */
882			pAd->MlmeAux.SupRateLen = SupRateLen;
883			NdisMoveMemory(pAd->MlmeAux.SupRate, SupRate,
884				       SupRateLen);
885			RTMPCheckRates(pAd, pAd->MlmeAux.SupRate,
886				       &pAd->MlmeAux.SupRateLen);
887			pAd->MlmeAux.ExtRateLen = ExtRateLen;
888			NdisMoveMemory(pAd->MlmeAux.ExtRate, ExtRate,
889				       ExtRateLen);
890			RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate,
891				       &pAd->MlmeAux.ExtRateLen);
892
893			NdisZeroMemory(pAd->StaActive.SupportedPhyInfo.MCSSet,
894				       16);
895
896			if (((pAd->StaCfg.WepStatus != Ndis802_11WEPEnabled)
897			     && (pAd->StaCfg.WepStatus !=
898				 Ndis802_11Encryption2Enabled))
899			    || (pAd->CommonCfg.HT_DisallowTKIP == FALSE)) {
900				bAllowNrate = TRUE;
901			}
902
903			pAd->MlmeAux.NewExtChannelOffset = NewExtChannelOffset;
904			pAd->MlmeAux.HtCapabilityLen = HtCapabilityLen;
905
906			RTMPZeroMemory(&pAd->MlmeAux.HtCapability,
907				       SIZE_HT_CAP_IE);
908			/* filter out un-supported ht rates */
909			if (((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0))
910			    && ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
911				&& (bAllowNrate))) {
912				RTMPMoveMemory(&pAd->MlmeAux.AddHtInfo,
913					       &AddHtInfo, SIZE_ADD_HT_INFO_IE);
914
915				/* StaActive.SupportedHtPhy.MCSSet stores Peer AP's 11n Rx capability */
916				NdisMoveMemory(pAd->StaActive.SupportedPhyInfo.
917					       MCSSet, HtCapability.MCSSet, 16);
918				pAd->MlmeAux.NewExtChannelOffset =
919				    NewExtChannelOffset;
920				pAd->MlmeAux.HtCapabilityLen = SIZE_HT_CAP_IE;
921				pAd->StaActive.SupportedPhyInfo.bHtEnable =
922				    TRUE;
923				if (PreNHtCapabilityLen > 0)
924					pAd->StaActive.SupportedPhyInfo.
925					    bPreNHt = TRUE;
926				RTMPCheckHt(pAd, BSSID_WCID, &HtCapability,
927					    &AddHtInfo);
928				/* Copy AP Parameter to StaActive.  This is also in LinkUp. */
929				DBGPRINT(RT_DEBUG_TRACE,
930					 ("PeerBeaconAtJoinAction! (MpduDensity=%d, MaxRAmpduFactor=%d, BW=%d)\n",
931					  pAd->StaActive.SupportedHtPhy.
932					  MpduDensity,
933					  pAd->StaActive.SupportedHtPhy.
934					  MaxRAmpduFactor,
935					  HtCapability.HtCapInfo.ChannelWidth));
936
937				if (AddHtInfoLen > 0) {
938					CentralChannel = AddHtInfo.ControlChan;
939					/* Check again the Bandwidth capability of this AP. */
940					if ((AddHtInfo.ControlChan > 2)
941					    && (AddHtInfo.AddHtInfo.
942						ExtChanOffset == EXTCHA_BELOW)
943					    && (HtCapability.HtCapInfo.
944						ChannelWidth == BW_40)) {
945						CentralChannel =
946						    AddHtInfo.ControlChan - 2;
947					} else
948					    if ((AddHtInfo.AddHtInfo.
949						 ExtChanOffset == EXTCHA_ABOVE)
950						&& (HtCapability.HtCapInfo.
951						    ChannelWidth == BW_40)) {
952						CentralChannel =
953						    AddHtInfo.ControlChan + 2;
954					}
955					/* Check Error . */
956					if (pAd->MlmeAux.CentralChannel !=
957					    CentralChannel)
958						DBGPRINT(RT_DEBUG_ERROR,
959							 ("PeerBeaconAtJoinAction HT===>Beacon Central Channel = %d, Control Channel = %d. Mlmeaux CentralChannel = %d\n",
960							  CentralChannel,
961							  AddHtInfo.ControlChan,
962							  pAd->MlmeAux.
963							  CentralChannel));
964
965					DBGPRINT(RT_DEBUG_TRACE,
966						 ("PeerBeaconAtJoinAction HT===>Central Channel = %d, Control Channel = %d,  .\n",
967						  CentralChannel,
968						  AddHtInfo.ControlChan));
969
970				}
971
972			} else {
973				/* To prevent error, let legacy AP must have same CentralChannel and Channel. */
974				if ((HtCapabilityLen == 0)
975				    && (PreNHtCapabilityLen == 0))
976					pAd->MlmeAux.CentralChannel =
977					    pAd->MlmeAux.Channel;
978
979				pAd->StaActive.SupportedPhyInfo.bHtEnable =
980				    FALSE;
981				pAd->MlmeAux.NewExtChannelOffset = 0xff;
982				RTMPZeroMemory(&pAd->MlmeAux.HtCapability,
983					       SIZE_HT_CAP_IE);
984				pAd->MlmeAux.HtCapabilityLen = 0;
985				RTMPZeroMemory(&pAd->MlmeAux.AddHtInfo,
986					       SIZE_ADD_HT_INFO_IE);
987			}
988
989			RTMPUpdateMlmeRate(pAd);
990
991			/* copy QOS related information */
992			if ((pAd->CommonCfg.bWmmCapable)
993			    || (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
994			    ) {
995				NdisMoveMemory(&pAd->MlmeAux.APEdcaParm,
996					       &EdcaParm, sizeof(struct rt_edca_parm));
997				NdisMoveMemory(&pAd->MlmeAux.APQbssLoad,
998					       &QbssLoad,
999					       sizeof(struct rt_qbss_load_parm));
1000				NdisMoveMemory(&pAd->MlmeAux.APQosCapability,
1001					       &QosCapability,
1002					       sizeof(struct rt_qos_capability_parm));
1003			} else {
1004				NdisZeroMemory(&pAd->MlmeAux.APEdcaParm,
1005					       sizeof(struct rt_edca_parm));
1006				NdisZeroMemory(&pAd->MlmeAux.APQbssLoad,
1007					       sizeof(struct rt_qbss_load_parm));
1008				NdisZeroMemory(&pAd->MlmeAux.APQosCapability,
1009					       sizeof(struct rt_qos_capability_parm));
1010			}
1011
1012			DBGPRINT(RT_DEBUG_TRACE,
1013				 ("SYNC - after JOIN, SupRateLen=%d, ExtRateLen=%d\n",
1014				  pAd->MlmeAux.SupRateLen,
1015				  pAd->MlmeAux.ExtRateLen));
1016
1017			if (AironetCellPowerLimit != 0xFF) {
1018				/*We need to change our TxPower for CCX 2.0 AP Control of Client Transmit Power */
1019				ChangeToCellPowerLimit(pAd,
1020						       AironetCellPowerLimit);
1021			} else	/*Used the default TX Power Percentage. */
1022				pAd->CommonCfg.TxPowerPercentage =
1023				    pAd->CommonCfg.TxPowerDefault;
1024
1025			pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1026			Status = MLME_SUCCESS;
1027			MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF,
1028				    2, &Status);
1029		}
1030		/* not to me BEACON, ignored */
1031	}
1032	/* sanity check fail, ignore this frame */
1033}
1034
1035/*
1036	==========================================================================
1037	Description:
1038		receive BEACON from peer
1039
1040	IRQL = DISPATCH_LEVEL
1041
1042	==========================================================================
1043 */
1044void PeerBeacon(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
1045{
1046	u8 Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN];
1047	char Ssid[MAX_LEN_OF_SSID];
1048	struct rt_cf_parm CfParm;
1049	u8 SsidLen, MessageToMe = 0, BssType, Channel, NewChannel, index = 0;
1050	u8 DtimCount = 0, DtimPeriod = 0, BcastFlag = 0;
1051	u16 CapabilityInfo, AtimWin, BeaconPeriod;
1052	LARGE_INTEGER TimeStamp;
1053	u16 TbttNumToNextWakeUp;
1054	u8 Erp;
1055	u8 SupRate[MAX_LEN_OF_SUPPORTED_RATES],
1056	    ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
1057	u8 SupRateLen, ExtRateLen;
1058	u8 CkipFlag;
1059	u16 LenVIE;
1060	u8 AironetCellPowerLimit;
1061	struct rt_edca_parm EdcaParm;
1062	struct rt_qbss_load_parm QbssLoad;
1063	struct rt_qos_capability_parm QosCapability;
1064	unsigned long RalinkIe;
1065	/* New for WPA security suites */
1066	u8 VarIE[MAX_VIE_LEN];	/* Total VIE length = MAX_VIE_LEN - -5 */
1067	struct rt_ndis_802_11_variable_ies *pVIE = NULL;
1068	struct rt_ht_capability_ie HtCapability;
1069	struct rt_add_ht_info_ie AddHtInfo;	/* AP might use this additional ht info IE */
1070	u8 HtCapabilityLen, PreNHtCapabilityLen;
1071	u8 AddHtInfoLen;
1072	u8 NewExtChannelOffset = 0xff;
1073
1074	if (!(INFRA_ON(pAd) || ADHOC_ON(pAd)
1075	    ))
1076		return;
1077
1078	/* Init Variable IE structure */
1079	pVIE = (struct rt_ndis_802_11_variable_ies *)VarIE;
1080	pVIE->Length = 0;
1081	RTMPZeroMemory(&HtCapability, sizeof(HtCapability));
1082	RTMPZeroMemory(&AddHtInfo, sizeof(struct rt_add_ht_info_ie));
1083
1084	if (PeerBeaconAndProbeRspSanity(pAd,
1085					Elem->Msg,
1086					Elem->MsgLen,
1087					Elem->Channel,
1088					Addr2,
1089					Bssid,
1090					Ssid,
1091					&SsidLen,
1092					&BssType,
1093					&BeaconPeriod,
1094					&Channel,
1095					&NewChannel,
1096					&TimeStamp,
1097					&CfParm,
1098					&AtimWin,
1099					&CapabilityInfo,
1100					&Erp,
1101					&DtimCount,
1102					&DtimPeriod,
1103					&BcastFlag,
1104					&MessageToMe,
1105					SupRate,
1106					&SupRateLen,
1107					ExtRate,
1108					&ExtRateLen,
1109					&CkipFlag,
1110					&AironetCellPowerLimit,
1111					&EdcaParm,
1112					&QbssLoad,
1113					&QosCapability,
1114					&RalinkIe,
1115					&HtCapabilityLen,
1116					&PreNHtCapabilityLen,
1117					&HtCapability,
1118					&AddHtInfoLen,
1119					&AddHtInfo,
1120					&NewExtChannelOffset, &LenVIE, pVIE)) {
1121		BOOLEAN is_my_bssid, is_my_ssid;
1122		unsigned long Bssidx, Now;
1123		struct rt_bss_entry *pBss;
1124		char RealRssi =
1125		    RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0),
1126				ConvertToRssi(pAd, Elem->Rssi1, RSSI_1),
1127				ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
1128
1129		is_my_bssid =
1130		    MAC_ADDR_EQUAL(Bssid, pAd->CommonCfg.Bssid) ? TRUE : FALSE;
1131		is_my_ssid =
1132		    SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid,
1133			       pAd->CommonCfg.SsidLen) ? TRUE : FALSE;
1134
1135		/* ignore BEACON not for my SSID */
1136		if ((!is_my_ssid) && (!is_my_bssid))
1137			return;
1138
1139		/* It means STA waits disassoc completely from this AP, ignores this beacon. */
1140		if (pAd->Mlme.CntlMachine.CurrState == CNTL_WAIT_DISASSOC)
1141			return;
1142
1143		/* Copy Control channel for this BSSID. */
1144		if (AddHtInfoLen != 0)
1145			Channel = AddHtInfo.ControlChan;
1146
1147		if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0))
1148			HtCapabilityLen = SIZE_HT_CAP_IE;
1149
1150		/* */
1151		/* Housekeeping "SsidBssTab" table for later-on ROAMing usage. */
1152		/* */
1153		Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel);
1154		if (Bssidx == BSS_NOT_FOUND) {
1155			/* discover new AP of this network, create BSS entry */
1156			Bssidx =
1157			    BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid,
1158					     SsidLen, BssType, BeaconPeriod,
1159					     &CfParm, AtimWin, CapabilityInfo,
1160					     SupRate, SupRateLen, ExtRate,
1161					     ExtRateLen, &HtCapability,
1162					     &AddHtInfo, HtCapabilityLen,
1163					     AddHtInfoLen, NewExtChannelOffset,
1164					     Channel, RealRssi, TimeStamp,
1165					     CkipFlag, &EdcaParm,
1166					     &QosCapability, &QbssLoad, LenVIE,
1167					     pVIE);
1168			if (Bssidx == BSS_NOT_FOUND)	/* return if BSS table full */
1169				return;
1170
1171			NdisMoveMemory(pAd->ScanTab.BssEntry[Bssidx].PTSF,
1172				       &Elem->Msg[24], 4);
1173			NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[0],
1174				       &Elem->TimeStamp.u.LowPart, 4);
1175			NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[4],
1176				       &Elem->TimeStamp.u.LowPart, 4);
1177
1178		}
1179
1180		if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0)
1181		    && (Channel != NewChannel)) {
1182			/* Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection). */
1183			/* In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results. */
1184			AsicSwitchChannel(pAd, 1, FALSE);
1185			AsicLockChannel(pAd, 1);
1186			LinkDown(pAd, FALSE);
1187			MlmeQueueInit(&pAd->Mlme.Queue);
1188			BssTableInit(&pAd->ScanTab);
1189			RTMPusecDelay(1000000);	/* use delay to prevent STA do reassoc */
1190
1191			/* channel sanity check */
1192			for (index = 0; index < pAd->ChannelListNum; index++) {
1193				if (pAd->ChannelList[index].Channel ==
1194				    NewChannel) {
1195					pAd->ScanTab.BssEntry[Bssidx].Channel =
1196					    NewChannel;
1197					pAd->CommonCfg.Channel = NewChannel;
1198					AsicSwitchChannel(pAd,
1199							  pAd->CommonCfg.
1200							  Channel, FALSE);
1201					AsicLockChannel(pAd,
1202							pAd->CommonCfg.Channel);
1203					DBGPRINT(RT_DEBUG_TRACE,
1204						 ("PeerBeacon - STA receive channel switch announcement IE (New Channel =%d)\n",
1205						  NewChannel));
1206					break;
1207				}
1208			}
1209
1210			if (index >= pAd->ChannelListNum) {
1211				DBGPRINT_ERR(("PeerBeacon(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum));
1212			}
1213		}
1214		/* if the ssid matched & bssid unmatched, we should select the bssid with large value. */
1215		/* This might happened when two STA start at the same time */
1216		if ((!is_my_bssid) && ADHOC_ON(pAd)) {
1217			int i;
1218
1219			/* Add the safeguard against the mismatch of adhoc wep status */
1220			if (pAd->StaCfg.WepStatus !=
1221			    pAd->ScanTab.BssEntry[Bssidx].WepStatus) {
1222				return;
1223			}
1224			/* collapse into the ADHOC network which has bigger BSSID value. */
1225			for (i = 0; i < 6; i++) {
1226				if (Bssid[i] > pAd->CommonCfg.Bssid[i]) {
1227					DBGPRINT(RT_DEBUG_TRACE,
1228						 ("SYNC - merge to the IBSS with bigger BSSID=%02x:%02x:%02x:%02x:%02x:%02x\n",
1229						  Bssid[0], Bssid[1], Bssid[2],
1230						  Bssid[3], Bssid[4],
1231						  Bssid[5]));
1232					AsicDisableSync(pAd);
1233					COPY_MAC_ADDR(pAd->CommonCfg.Bssid,
1234						      Bssid);
1235					AsicSetBssid(pAd, pAd->CommonCfg.Bssid);
1236					MakeIbssBeacon(pAd);	/* re-build BEACON frame */
1237					AsicEnableIbssSync(pAd);	/* copy BEACON frame to on-chip memory */
1238					is_my_bssid = TRUE;
1239					break;
1240				} else if (Bssid[i] < pAd->CommonCfg.Bssid[i])
1241					break;
1242			}
1243		}
1244
1245		NdisGetSystemUpTime(&Now);
1246		pBss = &pAd->ScanTab.BssEntry[Bssidx];
1247		pBss->Rssi = RealRssi;	/* lastest RSSI */
1248		pBss->LastBeaconRxTime = Now;	/* last RX timestamp */
1249
1250		/* */
1251		/* BEACON from my BSSID - either IBSS or INFRA network */
1252		/* */
1253		if (is_my_bssid) {
1254			struct rt_rxwi RxWI;
1255
1256			pAd->StaCfg.DtimCount = DtimCount;
1257			pAd->StaCfg.DtimPeriod = DtimPeriod;
1258			pAd->StaCfg.LastBeaconRxTime = Now;
1259
1260			RxWI.RSSI0 = Elem->Rssi0;
1261			RxWI.RSSI1 = Elem->Rssi1;
1262			RxWI.RSSI2 = Elem->Rssi2;
1263
1264			Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, &RxWI);
1265			if (AironetCellPowerLimit != 0xFF) {
1266				/* */
1267				/* We get the Cisco (ccx) "TxPower Limit" required */
1268				/* Changed to appropriate TxPower Limit for Ciso Compatible Extensions */
1269				/* */
1270				ChangeToCellPowerLimit(pAd,
1271						       AironetCellPowerLimit);
1272			} else {
1273				/* */
1274				/* AironetCellPowerLimit equal to 0xFF means the Cisco (ccx) "TxPower Limit" not exist. */
1275				/* Used the default TX Power Percentage, that set from UI. */
1276				/* */
1277				pAd->CommonCfg.TxPowerPercentage =
1278				    pAd->CommonCfg.TxPowerDefault;
1279			}
1280
1281			if (ADHOC_ON(pAd) && (CAP_IS_IBSS_ON(CapabilityInfo))) {
1282				u8 MaxSupportedRateIn500Kbps = 0;
1283				u8 idx;
1284				struct rt_mac_table_entry *pEntry;
1285
1286				/* supported rates array may not be sorted. sort it and find the maximum rate */
1287				for (idx = 0; idx < SupRateLen; idx++) {
1288					if (MaxSupportedRateIn500Kbps <
1289					    (SupRate[idx] & 0x7f))
1290						MaxSupportedRateIn500Kbps =
1291						    SupRate[idx] & 0x7f;
1292				}
1293
1294				for (idx = 0; idx < ExtRateLen; idx++) {
1295					if (MaxSupportedRateIn500Kbps <
1296					    (ExtRate[idx] & 0x7f))
1297						MaxSupportedRateIn500Kbps =
1298						    ExtRate[idx] & 0x7f;
1299				}
1300
1301				/* look up the existing table */
1302				pEntry = MacTableLookup(pAd, Addr2);
1303
1304				/* Ad-hoc mode is using MAC address as BA session. So we need to continuously find newly joined adhoc station by receiving beacon. */
1305				/* To prevent always check this, we use wcid == RESERVED_WCID to recognize it as newly joined adhoc station. */
1306				if ((ADHOC_ON(pAd)
1307				     && (Elem->Wcid == RESERVED_WCID))
1308				    || (pEntry
1309					&&
1310					((pEntry->LastBeaconRxTime +
1311					  ADHOC_ENTRY_BEACON_LOST_TIME) <
1312					 Now))) {
1313					if (pEntry == NULL)
1314						/* Another adhoc joining, add to our MAC table. */
1315						pEntry =
1316						    MacTableInsertEntry(pAd,
1317									Addr2,
1318									BSS0,
1319									FALSE);
1320
1321					if (StaAddMacTableEntry(pAd,
1322								pEntry,
1323								MaxSupportedRateIn500Kbps,
1324								&HtCapability,
1325								HtCapabilityLen,
1326								&AddHtInfo,
1327								AddHtInfoLen,
1328								CapabilityInfo)
1329					    == FALSE) {
1330						DBGPRINT(RT_DEBUG_TRACE,
1331							 ("ADHOC - Add Entry failed.\n"));
1332						return;
1333					}
1334
1335					if (pEntry &&
1336					    (Elem->Wcid == RESERVED_WCID)) {
1337						idx = pAd->StaCfg.DefaultKeyId;
1338						RTMP_STA_SECURITY_INFO_ADD(pAd,
1339									   BSS0,
1340									   idx,
1341									   pEntry);
1342					}
1343				}
1344
1345				if (pEntry && pEntry->ValidAsCLI)
1346					pEntry->LastBeaconRxTime = Now;
1347
1348				/* At least another peer in this IBSS, declare MediaState as CONNECTED */
1349				if (!OPSTATUS_TEST_FLAG
1350				    (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) {
1351					OPSTATUS_SET_FLAG(pAd,
1352							  fOP_STATUS_MEDIA_STATE_CONNECTED);
1353
1354					pAd->IndicateMediaState =
1355					    NdisMediaStateConnected;
1356					RTMP_IndicateMediaState(pAd);
1357					pAd->ExtraInfo = GENERAL_LINK_UP;
1358					AsicSetBssid(pAd, pAd->CommonCfg.Bssid);
1359
1360					/* 2003/03/12 - john */
1361					/* Make sure this entry in "ScanTab" table, thus complies to Microsoft's policy that */
1362					/* "site survey" result should always include the current connected network. */
1363					/* */
1364					Bssidx =
1365					    BssTableSearch(&pAd->ScanTab, Bssid,
1366							   Channel);
1367					if (Bssidx == BSS_NOT_FOUND) {
1368						Bssidx =
1369						    BssTableSetEntry(pAd,
1370								     &pAd->
1371								     ScanTab,
1372								     Bssid,
1373								     Ssid,
1374								     SsidLen,
1375								     BssType,
1376								     BeaconPeriod,
1377								     &CfParm,
1378								     AtimWin,
1379								     CapabilityInfo,
1380								     SupRate,
1381								     SupRateLen,
1382								     ExtRate,
1383								     ExtRateLen,
1384								     &HtCapability,
1385								     &AddHtInfo,
1386								     HtCapabilityLen,
1387								     AddHtInfoLen,
1388								     NewExtChannelOffset,
1389								     Channel,
1390								     RealRssi,
1391								     TimeStamp,
1392								     0,
1393								     &EdcaParm,
1394								     &QosCapability,
1395								     &QbssLoad,
1396								     LenVIE,
1397								     pVIE);
1398					}
1399					DBGPRINT(RT_DEBUG_TRACE,
1400						 ("ADHOC  fOP_STATUS_MEDIA_STATE_CONNECTED.\n"));
1401				}
1402			}
1403
1404			if (INFRA_ON(pAd)) {
1405				BOOLEAN bUseShortSlot, bUseBGProtection;
1406
1407				/* decide to use/change to - */
1408				/*      1. long slot (20 us) or short slot (9 us) time */
1409				/*      2. turn on/off RTS/CTS and/or CTS-to-self protection */
1410				/*      3. short preamble */
1411
1412				/*bUseShortSlot = pAd->CommonCfg.bUseShortSlotTime && CAP_IS_SHORT_SLOT(CapabilityInfo); */
1413				bUseShortSlot =
1414				    CAP_IS_SHORT_SLOT(CapabilityInfo);
1415				if (bUseShortSlot !=
1416				    OPSTATUS_TEST_FLAG(pAd,
1417						       fOP_STATUS_SHORT_SLOT_INUSED))
1418					AsicSetSlotTime(pAd, bUseShortSlot);
1419
1420				bUseBGProtection = (pAd->CommonCfg.UseBGProtection == 1) ||	/* always use */
1421				    ((pAd->CommonCfg.UseBGProtection == 0)
1422				     && ERP_IS_USE_PROTECTION(Erp));
1423
1424				if (pAd->CommonCfg.Channel > 14)	/* always no BG protection in A-band. falsely happened when switching A/G band to a dual-band AP */
1425					bUseBGProtection = FALSE;
1426
1427				if (bUseBGProtection !=
1428				    OPSTATUS_TEST_FLAG(pAd,
1429						       fOP_STATUS_BG_PROTECTION_INUSED))
1430				{
1431					if (bUseBGProtection) {
1432						OPSTATUS_SET_FLAG(pAd,
1433								  fOP_STATUS_BG_PROTECTION_INUSED);
1434						AsicUpdateProtect(pAd,
1435								  pAd->MlmeAux.
1436								  AddHtInfo.
1437								  AddHtInfo2.
1438								  OperaionMode,
1439								  (OFDMSETPROTECT
1440								   |
1441								   CCKSETPROTECT
1442								   |
1443								   ALLN_SETPROTECT),
1444								  FALSE,
1445								  (pAd->MlmeAux.
1446								   AddHtInfo.
1447								   AddHtInfo2.
1448								   NonGfPresent
1449								   == 1));
1450					} else {
1451						OPSTATUS_CLEAR_FLAG(pAd,
1452								    fOP_STATUS_BG_PROTECTION_INUSED);
1453						AsicUpdateProtect(pAd,
1454								  pAd->MlmeAux.
1455								  AddHtInfo.
1456								  AddHtInfo2.
1457								  OperaionMode,
1458								  (OFDMSETPROTECT
1459								   |
1460								   CCKSETPROTECT
1461								   |
1462								   ALLN_SETPROTECT),
1463								  TRUE,
1464								  (pAd->MlmeAux.
1465								   AddHtInfo.
1466								   AddHtInfo2.
1467								   NonGfPresent
1468								   == 1));
1469					}
1470
1471					DBGPRINT(RT_DEBUG_WARN,
1472						 ("SYNC - AP changed B/G protection to %d\n",
1473						  bUseBGProtection));
1474				}
1475				/* check Ht protection mode. and adhere to the Non-GF device indication by AP. */
1476				if ((AddHtInfoLen != 0) &&
1477				    ((AddHtInfo.AddHtInfo2.OperaionMode !=
1478				      pAd->MlmeAux.AddHtInfo.AddHtInfo2.
1479				      OperaionMode)
1480				     || (AddHtInfo.AddHtInfo2.NonGfPresent !=
1481					 pAd->MlmeAux.AddHtInfo.AddHtInfo2.
1482					 NonGfPresent))) {
1483					pAd->MlmeAux.AddHtInfo.AddHtInfo2.
1484					    NonGfPresent =
1485					    AddHtInfo.AddHtInfo2.NonGfPresent;
1486					pAd->MlmeAux.AddHtInfo.AddHtInfo2.
1487					    OperaionMode =
1488					    AddHtInfo.AddHtInfo2.OperaionMode;
1489					if (pAd->MlmeAux.AddHtInfo.AddHtInfo2.
1490					    NonGfPresent == 1) {
1491						AsicUpdateProtect(pAd,
1492								  pAd->MlmeAux.
1493								  AddHtInfo.
1494								  AddHtInfo2.
1495								  OperaionMode,
1496								  ALLN_SETPROTECT,
1497								  FALSE, TRUE);
1498					} else
1499						AsicUpdateProtect(pAd,
1500								  pAd->MlmeAux.
1501								  AddHtInfo.
1502								  AddHtInfo2.
1503								  OperaionMode,
1504								  ALLN_SETPROTECT,
1505								  FALSE, FALSE);
1506
1507					DBGPRINT(RT_DEBUG_TRACE,
1508						 ("SYNC - AP changed N OperaionMode to %d\n",
1509						  pAd->MlmeAux.AddHtInfo.
1510						  AddHtInfo2.OperaionMode));
1511				}
1512
1513				if (OPSTATUS_TEST_FLAG
1514				    (pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED)
1515				    && ERP_IS_USE_BARKER_PREAMBLE(Erp)) {
1516					MlmeSetTxPreamble(pAd,
1517							  Rt802_11PreambleLong);
1518					DBGPRINT(RT_DEBUG_TRACE,
1519						 ("SYNC - AP forced to use long preamble\n"));
1520				}
1521
1522				if (OPSTATUS_TEST_FLAG
1523				    (pAd, fOP_STATUS_WMM_INUSED)
1524				    && (EdcaParm.bValid == TRUE)
1525				    && (EdcaParm.EdcaUpdateCount !=
1526					pAd->CommonCfg.APEdcaParm.
1527					EdcaUpdateCount)) {
1528					DBGPRINT(RT_DEBUG_TRACE,
1529						 ("SYNC - AP change EDCA parameters(from %d to %d)\n",
1530						  pAd->CommonCfg.APEdcaParm.
1531						  EdcaUpdateCount,
1532						  EdcaParm.EdcaUpdateCount));
1533					AsicSetEdcaParm(pAd, &EdcaParm);
1534				}
1535				/* copy QOS related information */
1536				NdisMoveMemory(&pAd->CommonCfg.APQbssLoad,
1537					       &QbssLoad,
1538					       sizeof(struct rt_qbss_load_parm));
1539				NdisMoveMemory(&pAd->CommonCfg.APQosCapability,
1540					       &QosCapability,
1541					       sizeof(struct rt_qos_capability_parm));
1542			}
1543			/* only INFRASTRUCTURE mode support power-saving feature */
1544			if ((INFRA_ON(pAd) && (pAd->StaCfg.Psm == PWR_SAVE))
1545			    || (pAd->CommonCfg.bAPSDForcePowerSave)) {
1546				u8 FreeNumber;
1547				/*  1. AP has backlogged unicast-to-me frame, stay AWAKE, send PSPOLL */
1548				/*  2. AP has backlogged broadcast/multicast frame and we want those frames, stay AWAKE */
1549				/*  3. we have outgoing frames in TxRing or MgmtRing, better stay AWAKE */
1550				/*  4. Psm change to PWR_SAVE, but AP not been informed yet, we better stay AWAKE */
1551				/*  5. otherwise, put PHY back to sleep to save battery. */
1552				if (MessageToMe) {
1553#ifdef RTMP_MAC_PCI
1554					if (OPSTATUS_TEST_FLAG
1555					    (pAd, fOP_STATUS_PCIE_DEVICE)) {
1556						/* Restore to correct BBP R3 value */
1557						if (pAd->Antenna.field.RxPath >
1558						    1)
1559							RTMP_BBP_IO_WRITE8_BY_REG_ID
1560							    (pAd, BBP_R3,
1561							     pAd->StaCfg.BBPR3);
1562						/* Turn clk to 80Mhz. */
1563					}
1564#endif /* RTMP_MAC_PCI // */
1565					if (pAd->CommonCfg.bAPSDCapable
1566					    && pAd->CommonCfg.APEdcaParm.
1567					    bAPSDCapable
1568					    && pAd->CommonCfg.bAPSDAC_BE
1569					    && pAd->CommonCfg.bAPSDAC_BK
1570					    && pAd->CommonCfg.bAPSDAC_VI
1571					    && pAd->CommonCfg.bAPSDAC_VO) {
1572						pAd->CommonCfg.
1573						    bNeedSendTriggerFrame =
1574						    TRUE;
1575					} else
1576						RTMP_PS_POLL_ENQUEUE(pAd);
1577				} else if (BcastFlag && (DtimCount == 0)
1578					   && OPSTATUS_TEST_FLAG(pAd,
1579								 fOP_STATUS_RECEIVE_DTIM))
1580				{
1581#ifdef RTMP_MAC_PCI
1582					if (OPSTATUS_TEST_FLAG
1583					    (pAd, fOP_STATUS_PCIE_DEVICE)) {
1584						if (pAd->Antenna.field.RxPath >
1585						    1)
1586							RTMP_BBP_IO_WRITE8_BY_REG_ID
1587							    (pAd, BBP_R3,
1588							     pAd->StaCfg.BBPR3);
1589					}
1590#endif /* RTMP_MAC_PCI // */
1591				} else
1592				    if ((pAd->TxSwQueue[QID_AC_BK].Number != 0)
1593					|| (pAd->TxSwQueue[QID_AC_BE].Number !=
1594					    0)
1595					|| (pAd->TxSwQueue[QID_AC_VI].Number !=
1596					    0)
1597					|| (pAd->TxSwQueue[QID_AC_VO].Number !=
1598					    0)
1599					||
1600					(RTMPFreeTXDRequest
1601					 (pAd, QID_AC_BK, TX_RING_SIZE - 1,
1602					  &FreeNumber) != NDIS_STATUS_SUCCESS)
1603					||
1604					(RTMPFreeTXDRequest
1605					 (pAd, QID_AC_BE, TX_RING_SIZE - 1,
1606					  &FreeNumber) != NDIS_STATUS_SUCCESS)
1607					||
1608					(RTMPFreeTXDRequest
1609					 (pAd, QID_AC_VI, TX_RING_SIZE - 1,
1610					  &FreeNumber) != NDIS_STATUS_SUCCESS)
1611					||
1612					(RTMPFreeTXDRequest
1613					 (pAd, QID_AC_VO, TX_RING_SIZE - 1,
1614					  &FreeNumber) != NDIS_STATUS_SUCCESS)
1615					||
1616					(RTMPFreeTXDRequest
1617					 (pAd, QID_MGMT, MGMT_RING_SIZE - 1,
1618					  &FreeNumber) !=
1619					 NDIS_STATUS_SUCCESS)) {
1620					/* TODO: consider scheduled HCCA. might not be proper to use traditional DTIM-based power-saving scheme */
1621					/* can we cheat here (i.e. just check MGMT & AC_BE) for better performance? */
1622#ifdef RTMP_MAC_PCI
1623					if (OPSTATUS_TEST_FLAG
1624					    (pAd, fOP_STATUS_PCIE_DEVICE)) {
1625						if (pAd->Antenna.field.RxPath >
1626						    1)
1627							RTMP_BBP_IO_WRITE8_BY_REG_ID
1628							    (pAd, BBP_R3,
1629							     pAd->StaCfg.BBPR3);
1630					}
1631#endif /* RTMP_MAC_PCI // */
1632				} else {
1633					if ((pAd->CommonCfg.
1634					     bACMAPSDTr[QID_AC_VO])
1635					    || (pAd->CommonCfg.
1636						bACMAPSDTr[QID_AC_VI])
1637					    || (pAd->CommonCfg.
1638						bACMAPSDTr[QID_AC_BK])
1639					    || (pAd->CommonCfg.
1640						bACMAPSDTr[QID_AC_BE])) {
1641						/*
1642						   WMM Spec v1.0 3.6.2.4,
1643						   The WMM STA shall remain awake until it receives a
1644						   QoS Data or Null frame addressed to it, with the
1645						   EOSP subfield in QoS Control field set to 1.
1646
1647						   So we can not sleep here or we will suffer a case:
1648
1649						   PS Management Frame -->
1650						   Trigger frame -->
1651						   Beacon (TIM=0) (Beacon is closer to Trig frame) -->
1652						   Station goes to sleep -->
1653						   AP delivery queued UAPSD packets -->
1654						   Station can NOT receive the reply
1655
1656						   Maybe we need a timeout timer to avoid that we do
1657						   NOT receive the EOSP frame.
1658
1659						   We can not use More Data to check if SP is ended
1660						   due to MaxSPLength.
1661						 */
1662					} else {
1663						u16 NextDtim = DtimCount;
1664
1665						if (NextDtim == 0)
1666							NextDtim = DtimPeriod;
1667
1668						TbttNumToNextWakeUp =
1669						    pAd->StaCfg.
1670						    DefaultListenCount;
1671						if (OPSTATUS_TEST_FLAG
1672						    (pAd,
1673						     fOP_STATUS_RECEIVE_DTIM)
1674						    && (TbttNumToNextWakeUp >
1675							NextDtim))
1676							TbttNumToNextWakeUp =
1677							    NextDtim;
1678
1679						if (!OPSTATUS_TEST_FLAG
1680						    (pAd, fOP_STATUS_DOZE)) {
1681							/* Set a flag to go to sleep . Then after parse this RxDoneInterrupt, will go to sleep mode. */
1682							pAd->
1683							    ThisTbttNumToNextWakeUp
1684							    =
1685							    TbttNumToNextWakeUp;
1686							AsicSleepThenAutoWakeup
1687							    (pAd,
1688							     pAd->
1689							     ThisTbttNumToNextWakeUp);
1690						}
1691					}
1692				}
1693			}
1694		}
1695		/* not my BSSID, ignore it */
1696	}
1697	/* sanity check fail, ignore this frame */
1698}
1699
1700/*
1701	==========================================================================
1702	Description:
1703		Receive PROBE REQ from remote peer when operating in IBSS mode
1704	==========================================================================
1705 */
1706void PeerProbeReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
1707{
1708	u8 Addr2[MAC_ADDR_LEN];
1709	char Ssid[MAX_LEN_OF_SSID];
1710	u8 SsidLen;
1711	u8 HtLen, AddHtLen, NewExtLen;
1712	struct rt_header_802_11 ProbeRspHdr;
1713	int NStatus;
1714	u8 *pOutBuffer = NULL;
1715	unsigned long FrameLen = 0;
1716	LARGE_INTEGER FakeTimestamp;
1717	u8 DsLen = 1, IbssLen = 2;
1718	u8 LocalErpIe[3] = { IE_ERP, 1, 0 };
1719	BOOLEAN Privacy;
1720	u16 CapabilityInfo;
1721	u8 RSNIe = IE_WPA;
1722
1723	if (!ADHOC_ON(pAd))
1724		return;
1725
1726	if (PeerProbeReqSanity
1727	    (pAd, Elem->Msg, Elem->MsgLen, Addr2, Ssid, &SsidLen)) {
1728		if ((SsidLen == 0)
1729		    || SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid,
1730				  pAd->CommonCfg.SsidLen)) {
1731			/* allocate and send out ProbeRsp frame */
1732			NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);	/*Get an unused nonpaged memory */
1733			if (NStatus != NDIS_STATUS_SUCCESS)
1734				return;
1735
1736			/*pAd->StaCfg.AtimWin = 0;  // ?????? */
1737
1738			Privacy =
1739			    (pAd->StaCfg.WepStatus ==
1740			     Ndis802_11Encryption1Enabled)
1741			    || (pAd->StaCfg.WepStatus ==
1742				Ndis802_11Encryption2Enabled)
1743			    || (pAd->StaCfg.WepStatus ==
1744				Ndis802_11Encryption3Enabled);
1745			CapabilityInfo =
1746			    CAP_GENERATE(0, 1, Privacy,
1747					 (pAd->CommonCfg.TxPreamble ==
1748					  Rt802_11PreambleShort), 0, 0);
1749
1750			MakeOutgoingFrame(pOutBuffer, &FrameLen,
1751					  sizeof(struct rt_header_802_11), &ProbeRspHdr,
1752					  TIMESTAMP_LEN, &FakeTimestamp,
1753					  2, &pAd->CommonCfg.BeaconPeriod,
1754					  2, &CapabilityInfo,
1755					  1, &SsidIe,
1756					  1, &pAd->CommonCfg.SsidLen,
1757					  pAd->CommonCfg.SsidLen,
1758					  pAd->CommonCfg.Ssid, 1, &SupRateIe, 1,
1759					  &pAd->StaActive.SupRateLen,
1760					  pAd->StaActive.SupRateLen,
1761					  pAd->StaActive.SupRate, 1, &DsIe, 1,
1762					  &DsLen, 1, &pAd->CommonCfg.Channel, 1,
1763					  &IbssIe, 1, &IbssLen, 2,
1764					  &pAd->StaActive.AtimWin, END_OF_ARGS);
1765
1766			if (pAd->StaActive.ExtRateLen) {
1767				unsigned long tmp;
1768				MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
1769						  3, LocalErpIe,
1770						  1, &ExtRateIe,
1771						  1, &pAd->StaActive.ExtRateLen,
1772						  pAd->StaActive.ExtRateLen,
1773						  &pAd->StaActive.ExtRate,
1774						  END_OF_ARGS);
1775				FrameLen += tmp;
1776			}
1777			/* If adhoc secruity is set for WPA-None, append the cipher suite IE */
1778			if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) {
1779				unsigned long tmp;
1780				MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
1781						  1, &RSNIe,
1782						  1, &pAd->StaCfg.RSNIE_Len,
1783						  pAd->StaCfg.RSNIE_Len,
1784						  pAd->StaCfg.RSN_IE,
1785						  END_OF_ARGS);
1786				FrameLen += tmp;
1787			}
1788
1789			if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) {
1790				unsigned long TmpLen;
1791				u8 BROADCOM[4] = { 0x0, 0x90, 0x4c, 0x33 };
1792				HtLen = sizeof(pAd->CommonCfg.HtCapability);
1793				AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo);
1794				NewExtLen = 1;
1795				/*New extension channel offset IE is included in Beacon, Probe Rsp or channel Switch Announcement Frame */
1796				if (pAd->bBroadComHT == TRUE) {
1797					MakeOutgoingFrame(pOutBuffer + FrameLen,
1798							  &TmpLen, 1, &WpaIe, 4,
1799							  &BROADCOM[0],
1800							  pAd->MlmeAux.
1801							  HtCapabilityLen,
1802							  &pAd->MlmeAux.
1803							  HtCapability,
1804							  END_OF_ARGS);
1805				} else {
1806					MakeOutgoingFrame(pOutBuffer + FrameLen,
1807							  &TmpLen, 1, &HtCapIe,
1808							  1, &HtLen,
1809							  sizeof
1810							  (struct rt_ht_capability_ie),
1811							  &pAd->CommonCfg.
1812							  HtCapability, 1,
1813							  &AddHtInfoIe, 1,
1814							  &AddHtLen,
1815							  sizeof
1816							  (struct rt_add_ht_info_ie),
1817							  &pAd->CommonCfg.
1818							  AddHTInfo, 1,
1819							  &NewExtChanIe, 1,
1820							  &NewExtLen,
1821							  sizeof
1822							  (struct rt_new_ext_chan_ie),
1823							  &pAd->CommonCfg.
1824							  NewExtChanOffset,
1825							  END_OF_ARGS);
1826				}
1827				FrameLen += TmpLen;
1828			}
1829
1830			MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
1831			MlmeFreeMemory(pAd, pOutBuffer);
1832		}
1833	}
1834}
1835
1836void BeaconTimeoutAtJoinAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
1837{
1838	u16 Status;
1839	DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BeaconTimeoutAtJoinAction\n"));
1840	pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1841	Status = MLME_REJ_TIMEOUT;
1842	MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status);
1843}
1844
1845/*
1846	==========================================================================
1847	Description:
1848		Scan timeout procedure. basically add channel index by 1 and rescan
1849	==========================================================================
1850 */
1851void ScanTimeoutAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
1852{
1853	pAd->MlmeAux.Channel = NextChannel(pAd, pAd->MlmeAux.Channel);
1854
1855	/* Only one channel scanned for CISCO beacon request */
1856	if ((pAd->MlmeAux.ScanType == SCAN_CISCO_ACTIVE) ||
1857	    (pAd->MlmeAux.ScanType == SCAN_CISCO_PASSIVE) ||
1858	    (pAd->MlmeAux.ScanType == SCAN_CISCO_NOISE) ||
1859	    (pAd->MlmeAux.ScanType == SCAN_CISCO_CHANNEL_LOAD))
1860		pAd->MlmeAux.Channel = 0;
1861
1862	/* this routine will stop if pAd->MlmeAux.Channel == 0 */
1863	ScanNextChannel(pAd);
1864}
1865
1866/*
1867	==========================================================================
1868	Description:
1869	==========================================================================
1870 */
1871void InvalidStateWhenScan(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
1872{
1873	u16 Status;
1874	DBGPRINT(RT_DEBUG_TRACE,
1875		 ("AYNC - InvalidStateWhenScan(state=%ld). Reset SYNC machine\n",
1876		  pAd->Mlme.SyncMachine.CurrState));
1877	pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1878	Status = MLME_STATE_MACHINE_REJECT;
1879	MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status);
1880}
1881
1882/*
1883	==========================================================================
1884	Description:
1885	==========================================================================
1886 */
1887void InvalidStateWhenJoin(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
1888{
1889	u16 Status;
1890	DBGPRINT(RT_DEBUG_TRACE,
1891		 ("InvalidStateWhenJoin(state=%ld). Reset SYNC machine\n",
1892		  pAd->Mlme.SyncMachine.CurrState));
1893	pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1894	Status = MLME_STATE_MACHINE_REJECT;
1895	MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status);
1896}
1897
1898/*
1899	==========================================================================
1900	Description:
1901	==========================================================================
1902 */
1903void InvalidStateWhenStart(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
1904{
1905	u16 Status;
1906	DBGPRINT(RT_DEBUG_TRACE,
1907		 ("InvalidStateWhenStart(state=%ld). Reset SYNC machine\n",
1908		  pAd->Mlme.SyncMachine.CurrState));
1909	pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1910	Status = MLME_STATE_MACHINE_REJECT;
1911	MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status);
1912}
1913
1914/*
1915	==========================================================================
1916	Description:
1917
1918	IRQL = DISPATCH_LEVEL
1919
1920	==========================================================================
1921 */
1922void EnqueuePsPoll(struct rt_rtmp_adapter *pAd)
1923{
1924
1925	if (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeLegacy_PSP)
1926		pAd->PsPollFrame.FC.PwrMgmt = PWR_SAVE;
1927	MiniportMMRequest(pAd, 0, (u8 *)& pAd->PsPollFrame,
1928			  sizeof(struct rt_pspoll_frame));
1929}
1930
1931/*
1932	==========================================================================
1933	Description:
1934	==========================================================================
1935 */
1936void EnqueueProbeRequest(struct rt_rtmp_adapter *pAd)
1937{
1938	int NState;
1939	u8 *pOutBuffer;
1940	unsigned long FrameLen = 0;
1941	struct rt_header_802_11 Hdr80211;
1942
1943	DBGPRINT(RT_DEBUG_TRACE, ("force out a ProbeRequest ...\n"));
1944
1945	NState = MlmeAllocateMemory(pAd, &pOutBuffer);	/*Get an unused nonpaged memory */
1946	if (NState == NDIS_STATUS_SUCCESS) {
1947		MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0,
1948				 BROADCAST_ADDR, BROADCAST_ADDR);
1949
1950		/* this ProbeRequest explicitly specify SSID to reduce unwanted ProbeResponse */
1951		MakeOutgoingFrame(pOutBuffer, &FrameLen,
1952				  sizeof(struct rt_header_802_11), &Hdr80211,
1953				  1, &SsidIe,
1954				  1, &pAd->CommonCfg.SsidLen,
1955				  pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid,
1956				  1, &SupRateIe,
1957				  1, &pAd->StaActive.SupRateLen,
1958				  pAd->StaActive.SupRateLen,
1959				  pAd->StaActive.SupRate, END_OF_ARGS);
1960		MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
1961		MlmeFreeMemory(pAd, pOutBuffer);
1962	}
1963
1964}
1965
1966BOOLEAN ScanRunning(struct rt_rtmp_adapter *pAd)
1967{
1968	return (pAd->Mlme.SyncMachine.CurrState == SCAN_LISTEN) ? TRUE : FALSE;
1969}
1970