• 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	connect.c
29
30	Abstract:
31
32	Revision History:
33	Who			When			What
34	--------	----------		----------------------------------------------
35	John			2004-08-08			Major modification from RT2560
36*/
37#include "../rt_config.h"
38
39u8 CipherSuiteWpaNoneTkip[] = {
40	0x00, 0x50, 0xf2, 0x01,	/* oui */
41	0x01, 0x00,		/* Version */
42	0x00, 0x50, 0xf2, 0x02,	/* Multicast */
43	0x01, 0x00,		/* Number of unicast */
44	0x00, 0x50, 0xf2, 0x02,	/* unicast */
45	0x01, 0x00,		/* number of authentication method */
46	0x00, 0x50, 0xf2, 0x00	/* authentication */
47};
48
49u8 CipherSuiteWpaNoneTkipLen =
50    (sizeof(CipherSuiteWpaNoneTkip) / sizeof(u8));
51
52u8 CipherSuiteWpaNoneAes[] = {
53	0x00, 0x50, 0xf2, 0x01,	/* oui */
54	0x01, 0x00,		/* Version */
55	0x00, 0x50, 0xf2, 0x04,	/* Multicast */
56	0x01, 0x00,		/* Number of unicast */
57	0x00, 0x50, 0xf2, 0x04,	/* unicast */
58	0x01, 0x00,		/* number of authentication method */
59	0x00, 0x50, 0xf2, 0x00	/* authentication */
60};
61
62u8 CipherSuiteWpaNoneAesLen =
63    (sizeof(CipherSuiteWpaNoneAes) / sizeof(u8));
64
65/* The following MACRO is called after 1. starting an new IBSS, 2. successfully JOIN an IBSS, */
66/* or 3. successfully ASSOCIATE to a BSS, 4. successfully RE_ASSOCIATE to a BSS */
67/* All settings successfuly negotiated furing MLME state machines become final settings */
68/* and are copied to pAd->StaActive */
69#define COPY_SETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(_pAd)                                 \
70{                                                                                       \
71	NdisZeroMemory((_pAd)->CommonCfg.Ssid, MAX_LEN_OF_SSID);							\
72	(_pAd)->CommonCfg.SsidLen = (_pAd)->MlmeAux.SsidLen;                                \
73	NdisMoveMemory((_pAd)->CommonCfg.Ssid, (_pAd)->MlmeAux.Ssid, (_pAd)->MlmeAux.SsidLen); \
74	COPY_MAC_ADDR((_pAd)->CommonCfg.Bssid, (_pAd)->MlmeAux.Bssid);                      \
75	(_pAd)->CommonCfg.Channel = (_pAd)->MlmeAux.Channel;                                \
76	(_pAd)->CommonCfg.CentralChannel = (_pAd)->MlmeAux.CentralChannel;                  \
77	(_pAd)->StaActive.Aid = (_pAd)->MlmeAux.Aid;                                        \
78	(_pAd)->StaActive.AtimWin = (_pAd)->MlmeAux.AtimWin;                                \
79	(_pAd)->StaActive.CapabilityInfo = (_pAd)->MlmeAux.CapabilityInfo;                  \
80	(_pAd)->CommonCfg.BeaconPeriod = (_pAd)->MlmeAux.BeaconPeriod;                      \
81	(_pAd)->StaActive.CfpMaxDuration = (_pAd)->MlmeAux.CfpMaxDuration;                  \
82	(_pAd)->StaActive.CfpPeriod = (_pAd)->MlmeAux.CfpPeriod;                            \
83	(_pAd)->StaActive.SupRateLen = (_pAd)->MlmeAux.SupRateLen;                          \
84	NdisMoveMemory((_pAd)->StaActive.SupRate, (_pAd)->MlmeAux.SupRate, (_pAd)->MlmeAux.SupRateLen);\
85	(_pAd)->StaActive.ExtRateLen = (_pAd)->MlmeAux.ExtRateLen;                          \
86	NdisMoveMemory((_pAd)->StaActive.ExtRate, (_pAd)->MlmeAux.ExtRate, (_pAd)->MlmeAux.ExtRateLen);\
87	NdisMoveMemory(&(_pAd)->CommonCfg.APEdcaParm, &(_pAd)->MlmeAux.APEdcaParm, sizeof(struct rt_edca_parm));\
88	NdisMoveMemory(&(_pAd)->CommonCfg.APQosCapability, &(_pAd)->MlmeAux.APQosCapability, sizeof(struct rt_qos_capability_parm));\
89	NdisMoveMemory(&(_pAd)->CommonCfg.APQbssLoad, &(_pAd)->MlmeAux.APQbssLoad, sizeof(struct rt_qbss_load_parm));\
90	COPY_MAC_ADDR((_pAd)->MacTab.Content[BSSID_WCID].Addr, (_pAd)->MlmeAux.Bssid);      \
91	(_pAd)->MacTab.Content[BSSID_WCID].Aid = (_pAd)->MlmeAux.Aid;                       \
92	(_pAd)->MacTab.Content[BSSID_WCID].PairwiseKey.CipherAlg = (_pAd)->StaCfg.PairCipher;\
93	COPY_MAC_ADDR((_pAd)->MacTab.Content[BSSID_WCID].PairwiseKey.BssId, (_pAd)->MlmeAux.Bssid);\
94	(_pAd)->MacTab.Content[BSSID_WCID].RateLen = (_pAd)->StaActive.SupRateLen + (_pAd)->StaActive.ExtRateLen;\
95}
96
97/*
98	==========================================================================
99	Description:
100
101	IRQL = PASSIVE_LEVEL
102
103	==========================================================================
104*/
105void MlmeCntlInit(struct rt_rtmp_adapter *pAd,
106		  struct rt_state_machine *S, OUT STATE_MACHINE_FUNC Trans[])
107{
108	/* Control state machine differs from other state machines, the interface */
109	/* follows the standard interface */
110	pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
111}
112
113/*
114	==========================================================================
115	Description:
116
117	IRQL = DISPATCH_LEVEL
118
119	==========================================================================
120*/
121void MlmeCntlMachinePerformAction(struct rt_rtmp_adapter *pAd,
122				  struct rt_state_machine *S,
123				  struct rt_mlme_queue_elem *Elem)
124{
125	switch (pAd->Mlme.CntlMachine.CurrState) {
126	case CNTL_IDLE:
127		CntlIdleProc(pAd, Elem);
128		break;
129	case CNTL_WAIT_DISASSOC:
130		CntlWaitDisassocProc(pAd, Elem);
131		break;
132	case CNTL_WAIT_JOIN:
133		CntlWaitJoinProc(pAd, Elem);
134		break;
135
136		/* CNTL_WAIT_REASSOC is the only state in CNTL machine that does */
137		/* not triggered directly or indirectly by "RTMPSetInformation(OID_xxx)". */
138		/* Therefore not protected by NDIS's "only one outstanding OID request" */
139		/* rule. Which means NDIS may SET OID in the middle of ROAMing attempts. */
140		/* Current approach is to block new SET request at RTMPSetInformation() */
141		/* when CntlMachine.CurrState is not CNTL_IDLE */
142	case CNTL_WAIT_REASSOC:
143		CntlWaitReassocProc(pAd, Elem);
144		break;
145
146	case CNTL_WAIT_START:
147		CntlWaitStartProc(pAd, Elem);
148		break;
149	case CNTL_WAIT_AUTH:
150		CntlWaitAuthProc(pAd, Elem);
151		break;
152	case CNTL_WAIT_AUTH2:
153		CntlWaitAuthProc2(pAd, Elem);
154		break;
155	case CNTL_WAIT_ASSOC:
156		CntlWaitAssocProc(pAd, Elem);
157		break;
158
159	case CNTL_WAIT_OID_LIST_SCAN:
160		if (Elem->MsgType == MT2_SCAN_CONF) {
161			/* Resume TxRing after SCANING complete. We hope the out-of-service time */
162			/* won't be too long to let upper layer time-out the waiting frames */
163			RTMPResumeMsduTransmission(pAd);
164
165			pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
166
167			/* */
168			/* Set LED status to previous status. */
169			/* */
170			if (pAd->bLedOnScanning) {
171				pAd->bLedOnScanning = FALSE;
172				RTMPSetLED(pAd, pAd->LedStatus);
173			}
174		}
175		break;
176
177	case CNTL_WAIT_OID_DISASSOC:
178		if (Elem->MsgType == MT2_DISASSOC_CONF) {
179			LinkDown(pAd, FALSE);
180			pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
181		}
182		break;
183#ifdef RTMP_MAC_USB
184		/* */
185		/* This state is for that we want to connect to an AP but */
186		/* it didn't find on BSS List table. So we need to scan the air first, */
187		/* after that we can try to connect to the desired AP if available. */
188		/* */
189	case CNTL_WAIT_SCAN_FOR_CONNECT:
190		if (Elem->MsgType == MT2_SCAN_CONF) {
191			/* Resume TxRing after SCANING complete. We hope the out-of-service time */
192			/* won't be too long to let upper layer time-out the waiting frames */
193			RTMPResumeMsduTransmission(pAd);
194#ifdef CCX_SUPPORT
195			if (pAd->StaCfg.CCXReqType != MSRN_TYPE_UNUSED) {
196				/* Cisco scan request is finished, prepare beacon report */
197				MlmeEnqueue(pAd, AIRONET_STATE_MACHINE,
198					    MT2_AIRONET_SCAN_DONE, 0, NULL);
199			}
200#endif /* CCX_SUPPORT // */
201			pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
202
203			/* */
204			/* Check if we can connect to. */
205			/* */
206			BssTableSsidSort(pAd, &pAd->MlmeAux.SsidBssTab,
207					 (char *) pAd->MlmeAux.
208					 AutoReconnectSsid,
209					 pAd->MlmeAux.AutoReconnectSsidLen);
210			if (pAd->MlmeAux.SsidBssTab.BssNr > 0) {
211				MlmeAutoReconnectLastSSID(pAd);
212			}
213		}
214		break;
215#endif /* RTMP_MAC_USB // */
216	default:
217		DBGPRINT_ERR(("ERROR! CNTL - Illegal message type(=%ld)",
218			      Elem->MsgType));
219		break;
220	}
221}
222
223/*
224	==========================================================================
225	Description:
226
227	IRQL = DISPATCH_LEVEL
228
229	==========================================================================
230*/
231void CntlIdleProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
232{
233	struct rt_mlme_disassoc_req DisassocReq;
234
235	if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
236		return;
237
238	switch (Elem->MsgType) {
239	case OID_802_11_SSID:
240		CntlOidSsidProc(pAd, Elem);
241		break;
242
243	case OID_802_11_BSSID:
244		CntlOidRTBssidProc(pAd, Elem);
245		break;
246
247	case OID_802_11_BSSID_LIST_SCAN:
248		CntlOidScanProc(pAd, Elem);
249		break;
250
251	case OID_802_11_DISASSOCIATE:
252		DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid,
253				 REASON_DISASSOC_STA_LEAVING);
254		MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ,
255			    sizeof(struct rt_mlme_disassoc_req), &DisassocReq);
256		pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC;
257
258		if (pAd->StaCfg.WpaSupplicantUP !=
259		    WPA_SUPPLICANT_ENABLE_WITH_WEB_UI) {
260			/* Set the AutoReconnectSsid to prevent it reconnect to old SSID */
261			/* Since calling this indicate user don't want to connect to that SSID anymore. */
262			pAd->MlmeAux.AutoReconnectSsidLen = 32;
263			NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid,
264				       pAd->MlmeAux.AutoReconnectSsidLen);
265		}
266		break;
267
268	case MT2_MLME_ROAMING_REQ:
269		CntlMlmeRoamingProc(pAd, Elem);
270		break;
271
272	case OID_802_11_MIC_FAILURE_REPORT_FRAME:
273		WpaMicFailureReportFrame(pAd, Elem);
274		break;
275
276	default:
277		DBGPRINT(RT_DEBUG_TRACE,
278			 ("CNTL - Illegal message in CntlIdleProc(MsgType=%ld)\n",
279			  Elem->MsgType));
280		break;
281	}
282}
283
284void CntlOidScanProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
285{
286	struct rt_mlme_scan_req ScanReq;
287	unsigned long BssIdx = BSS_NOT_FOUND;
288	struct rt_bss_entry CurrBss;
289
290	/* record current BSS if network is connected. */
291	/* 2003-2-13 do not include current IBSS if this is the only STA in this IBSS. */
292	if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) {
293		BssIdx =
294		    BssSsidTableSearch(&pAd->ScanTab, pAd->CommonCfg.Bssid,
295				       (u8 *)pAd->CommonCfg.Ssid,
296				       pAd->CommonCfg.SsidLen,
297				       pAd->CommonCfg.Channel);
298		if (BssIdx != BSS_NOT_FOUND) {
299			NdisMoveMemory(&CurrBss, &pAd->ScanTab.BssEntry[BssIdx],
300				       sizeof(struct rt_bss_entry));
301		}
302	}
303	/* clean up previous SCAN result, add current BSS back to table if any */
304	BssTableInit(&pAd->ScanTab);
305	if (BssIdx != BSS_NOT_FOUND) {
306		/* DDK Note: If the NIC is associated with a particular BSSID and SSID */
307		/*    that are not contained in the list of BSSIDs generated by this scan, the */
308		/*    BSSID description of the currently associated BSSID and SSID should be */
309		/*    appended to the list of BSSIDs in the NIC's database. */
310		/* To ensure this, we append this BSS as the first entry in SCAN result */
311		NdisMoveMemory(&pAd->ScanTab.BssEntry[0], &CurrBss,
312			       sizeof(struct rt_bss_entry));
313		pAd->ScanTab.BssNr = 1;
314	}
315
316	ScanParmFill(pAd, &ScanReq, (char *)Elem->Msg, Elem->MsgLen, BSS_ANY,
317		     SCAN_ACTIVE);
318	MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ,
319		    sizeof(struct rt_mlme_scan_req), &ScanReq);
320	pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
321}
322
323/*
324	==========================================================================
325	Description:
326		Before calling this routine, user desired SSID should already been
327		recorded in CommonCfg.Ssid[]
328	IRQL = DISPATCH_LEVEL
329
330	==========================================================================
331*/
332void CntlOidSsidProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
333{
334	struct rt_ndis_802_11_ssid * pOidSsid = (struct rt_ndis_802_11_ssid *) Elem->Msg;
335	struct rt_mlme_disassoc_req DisassocReq;
336	unsigned long Now;
337
338	/* Step 1. record the desired user settings to MlmeAux */
339	NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID);
340	NdisMoveMemory(pAd->MlmeAux.Ssid, pOidSsid->Ssid, pOidSsid->SsidLength);
341	pAd->MlmeAux.SsidLen = (u8)pOidSsid->SsidLength;
342	NdisZeroMemory(pAd->MlmeAux.Bssid, MAC_ADDR_LEN);
343	pAd->MlmeAux.BssType = pAd->StaCfg.BssType;
344
345	pAd->StaCfg.bAutoConnectByBssid = FALSE;
346
347	/* */
348	/* Update Reconnect Ssid, that user desired to connect. */
349	/* */
350	NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, MAX_LEN_OF_SSID);
351	NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.Ssid,
352		       pAd->MlmeAux.SsidLen);
353	pAd->MlmeAux.AutoReconnectSsidLen = pAd->MlmeAux.SsidLen;
354
355	/* step 2. find all matching BSS in the lastest SCAN result (inBssTab) */
356	/*    & log them into MlmeAux.SsidBssTab for later-on iteration. Sort by RSSI order */
357	BssTableSsidSort(pAd, &pAd->MlmeAux.SsidBssTab,
358			 (char *)pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
359
360	DBGPRINT(RT_DEBUG_TRACE,
361		 ("CntlOidSsidProc():CNTL - %d BSS of %d BSS match the desire (%d)SSID - %s\n",
362		  pAd->MlmeAux.SsidBssTab.BssNr, pAd->ScanTab.BssNr,
363		  pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid));
364	NdisGetSystemUpTime(&Now);
365
366	if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) &&
367	    (pAd->CommonCfg.SsidLen ==
368	     pAd->MlmeAux.SsidBssTab.BssEntry[0].SsidLen)
369	    && NdisEqualMemory(pAd->CommonCfg.Ssid,
370			       pAd->MlmeAux.SsidBssTab.BssEntry[0].Ssid,
371			       pAd->CommonCfg.SsidLen)
372	    && MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid,
373			      pAd->MlmeAux.SsidBssTab.BssEntry[0].Bssid)) {
374		/* Case 1. already connected with an AP who has the desired SSID */
375		/*         with highest RSSI */
376
377		/* Add checking Mode "LEAP" for CCX 1.0 */
378		if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
379		     (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
380		     (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
381		     (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
382		    ) &&
383		    (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) {
384			/* case 1.1 For WPA, WPA-PSK, if the 1x port is not secured, we have to redo */
385			/*          connection process */
386			DBGPRINT(RT_DEBUG_TRACE,
387				 ("CntlOidSsidProc():CNTL - disassociate with current AP...\n"));
388			DisassocParmFill(pAd, &DisassocReq,
389					 pAd->CommonCfg.Bssid,
390					 REASON_DISASSOC_STA_LEAVING);
391			MlmeEnqueue(pAd, ASSOC_STATE_MACHINE,
392				    MT2_MLME_DISASSOC_REQ,
393				    sizeof(struct rt_mlme_disassoc_req),
394				    &DisassocReq);
395			pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
396		} else if (pAd->bConfigChanged == TRUE) {
397			/* case 1.2 Important Config has changed, we have to reconnect to the same AP */
398			DBGPRINT(RT_DEBUG_TRACE,
399				 ("CntlOidSsidProc():CNTL - disassociate with current AP Because config changed...\n"));
400			DisassocParmFill(pAd, &DisassocReq,
401					 pAd->CommonCfg.Bssid,
402					 REASON_DISASSOC_STA_LEAVING);
403			MlmeEnqueue(pAd, ASSOC_STATE_MACHINE,
404				    MT2_MLME_DISASSOC_REQ,
405				    sizeof(struct rt_mlme_disassoc_req),
406				    &DisassocReq);
407			pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
408		} else {
409			/* case 1.3. already connected to the SSID with highest RSSI. */
410			DBGPRINT(RT_DEBUG_TRACE,
411				 ("CntlOidSsidProc():CNTL - already with this BSSID. ignore this SET_SSID request\n"));
412			/* */
413			/* (HCT 12.1) 1c_wlan_mediaevents required */
414			/* media connect events are indicated when associating with the same AP */
415			/* */
416			if (INFRA_ON(pAd)) {
417				/* */
418				/* Since MediaState already is NdisMediaStateConnected */
419				/* We just indicate the connect event again to meet the WHQL required. */
420				/* */
421				pAd->IndicateMediaState =
422				    NdisMediaStateConnected;
423				RTMP_IndicateMediaState(pAd);
424				pAd->ExtraInfo = GENERAL_LINK_UP;	/* Update extra information to link is up */
425			}
426
427			pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
428			RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1,
429						&pAd->MlmeAux.Bssid[0], NULL,
430						0);
431		}
432	} else if (INFRA_ON(pAd)) {
433		/* */
434		/* For RT61 */
435		/* [88888] OID_802_11_SSID should have returned NDTEST_WEP_AP2(Returned: ) */
436		/* RT61 may lost SSID, and not connect to NDTEST_WEP_AP2 and will connect to NDTEST_WEP_AP2 by Autoreconnect */
437		/* But media status is connected, so the SSID not report correctly. */
438		/* */
439		if (!SSID_EQUAL
440		    (pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen,
441		     pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen)) {
442			/* */
443			/* Different SSID means not Roaming case, so we let LinkDown() to Indicate a disconnect event. */
444			/* */
445			pAd->MlmeAux.CurrReqIsFromNdis = TRUE;
446		}
447		/* case 2. active INFRA association existent */
448		/*    roaming is done within miniport driver, nothing to do with configuration */
449		/*    utility. so upon a new SET(OID_802_11_SSID) is received, we just */
450		/*    disassociate with the current associated AP, */
451		/*    then perform a new association with this new SSID, no matter the */
452		/*    new/old SSID are the same or not. */
453		DBGPRINT(RT_DEBUG_TRACE,
454			 ("CntlOidSsidProc():CNTL - disassociate with current AP...\n"));
455		DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid,
456				 REASON_DISASSOC_STA_LEAVING);
457		MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ,
458			    sizeof(struct rt_mlme_disassoc_req), &DisassocReq);
459		pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
460	} else {
461		if (ADHOC_ON(pAd)) {
462			DBGPRINT(RT_DEBUG_TRACE,
463				 ("CntlOidSsidProc():CNTL - drop current ADHOC\n"));
464			LinkDown(pAd, FALSE);
465			OPSTATUS_CLEAR_FLAG(pAd,
466					    fOP_STATUS_MEDIA_STATE_CONNECTED);
467			pAd->IndicateMediaState = NdisMediaStateDisconnected;
468			RTMP_IndicateMediaState(pAd);
469			pAd->ExtraInfo = GENERAL_LINK_DOWN;
470			DBGPRINT(RT_DEBUG_TRACE,
471				 ("CntlOidSsidProc():NDIS_STATUS_MEDIA_DISCONNECT Event C!\n"));
472		}
473
474		if ((pAd->MlmeAux.SsidBssTab.BssNr == 0) &&
475		    (pAd->StaCfg.bAutoReconnect == TRUE) &&
476		    (pAd->MlmeAux.BssType == BSS_INFRA) &&
477		    (MlmeValidateSSID(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen)
478		     == TRUE)
479		    ) {
480			struct rt_mlme_scan_req ScanReq;
481
482			DBGPRINT(RT_DEBUG_TRACE,
483				 ("CntlOidSsidProc():CNTL - No matching BSS, start a new scan\n"));
484			ScanParmFill(pAd, &ScanReq, (char *)pAd->MlmeAux.Ssid,
485				     pAd->MlmeAux.SsidLen, BSS_ANY,
486				     SCAN_ACTIVE);
487			MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ,
488				    sizeof(struct rt_mlme_scan_req), &ScanReq);
489			pAd->Mlme.CntlMachine.CurrState =
490			    CNTL_WAIT_OID_LIST_SCAN;
491			/* Reset Missed scan number */
492			pAd->StaCfg.LastScanTime = Now;
493		} else {
494			pAd->MlmeAux.BssIdx = 0;
495			IterateOnBssTab(pAd);
496		}
497	}
498}
499
500/*
501	==========================================================================
502	Description:
503
504	IRQL = DISPATCH_LEVEL
505
506	==========================================================================
507*/
508void CntlOidRTBssidProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
509{
510	unsigned long BssIdx;
511	u8 *pOidBssid = (u8 *)Elem->Msg;
512	struct rt_mlme_disassoc_req DisassocReq;
513	struct rt_mlme_join_req JoinReq;
514
515	/* record user desired settings */
516	COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pOidBssid);
517	pAd->MlmeAux.BssType = pAd->StaCfg.BssType;
518
519	/* find the desired BSS in the latest SCAN result table */
520	BssIdx = BssTableSearch(&pAd->ScanTab, pOidBssid, pAd->MlmeAux.Channel);
521	if (BssIdx == BSS_NOT_FOUND) {
522		struct rt_mlme_scan_req ScanReq;
523
524		DBGPRINT(RT_DEBUG_TRACE,
525			 ("CNTL - BSSID not found. reply NDIS_STATUS_NOT_ACCEPTED\n"));
526		/*pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; */
527
528		DBGPRINT(RT_DEBUG_TRACE,
529			 ("CNTL - BSSID not found. start a new scan\n"));
530		ScanParmFill(pAd, &ScanReq, (char *)pAd->MlmeAux.Ssid,
531			     pAd->MlmeAux.SsidLen, BSS_ANY, SCAN_ACTIVE);
532		MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ,
533			    sizeof(struct rt_mlme_scan_req), &ScanReq);
534		pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
535		/* Reset Missed scan number */
536		NdisGetSystemUpTime(&pAd->StaCfg.LastScanTime);
537		return;
538	}
539	/* */
540	/* Update Reconnect Ssid, that user desired to connect. */
541	/* */
542	NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, MAX_LEN_OF_SSID);
543	pAd->MlmeAux.AutoReconnectSsidLen =
544	    pAd->ScanTab.BssEntry[BssIdx].SsidLen;
545	NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid,
546		       pAd->ScanTab.BssEntry[BssIdx].Ssid,
547		       pAd->ScanTab.BssEntry[BssIdx].SsidLen);
548
549	/* copy the matched BSS entry from ScanTab to MlmeAux.SsidBssTab. Why? */
550	/* Because we need this entry to become the JOIN target in later on SYNC state machine */
551	pAd->MlmeAux.BssIdx = 0;
552	pAd->MlmeAux.SsidBssTab.BssNr = 1;
553	NdisMoveMemory(&pAd->MlmeAux.SsidBssTab.BssEntry[0],
554		       &pAd->ScanTab.BssEntry[BssIdx], sizeof(struct rt_bss_entry));
555
556	/* Add SSID into MlmeAux for site surey joining hidden SSID */
557	pAd->MlmeAux.SsidLen = pAd->ScanTab.BssEntry[BssIdx].SsidLen;
558	NdisMoveMemory(pAd->MlmeAux.Ssid, pAd->ScanTab.BssEntry[BssIdx].Ssid,
559		       pAd->MlmeAux.SsidLen);
560
561	{
562		if (INFRA_ON(pAd)) {
563			/* disassoc from current AP first */
564			DBGPRINT(RT_DEBUG_TRACE,
565				 ("CNTL - disassociate with current AP ...\n"));
566			DisassocParmFill(pAd, &DisassocReq,
567					 pAd->CommonCfg.Bssid,
568					 REASON_DISASSOC_STA_LEAVING);
569			MlmeEnqueue(pAd, ASSOC_STATE_MACHINE,
570				    MT2_MLME_DISASSOC_REQ,
571				    sizeof(struct rt_mlme_disassoc_req),
572				    &DisassocReq);
573
574			pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
575		} else {
576			if (ADHOC_ON(pAd)) {
577				DBGPRINT(RT_DEBUG_TRACE,
578					 ("CNTL - drop current ADHOC\n"));
579				LinkDown(pAd, FALSE);
580				OPSTATUS_CLEAR_FLAG(pAd,
581						    fOP_STATUS_MEDIA_STATE_CONNECTED);
582				pAd->IndicateMediaState =
583				    NdisMediaStateDisconnected;
584				RTMP_IndicateMediaState(pAd);
585				pAd->ExtraInfo = GENERAL_LINK_DOWN;
586				DBGPRINT(RT_DEBUG_TRACE,
587					 ("NDIS_STATUS_MEDIA_DISCONNECT Event C!\n"));
588			}
589			/* Change the wepstatus to original wepstatus */
590			pAd->StaCfg.WepStatus = pAd->StaCfg.OrigWepStatus;
591			pAd->StaCfg.PairCipher = pAd->StaCfg.OrigWepStatus;
592			pAd->StaCfg.GroupCipher = pAd->StaCfg.OrigWepStatus;
593
594			/* Check cipher suite, AP must have more secured cipher than station setting */
595			/* Set the Pairwise and Group cipher to match the intended AP setting */
596			/* We can only connect to AP with less secured cipher setting */
597			if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA)
598			    || (pAd->StaCfg.AuthMode ==
599				Ndis802_11AuthModeWPAPSK)) {
600				pAd->StaCfg.GroupCipher =
601				    pAd->ScanTab.BssEntry[BssIdx].WPA.
602				    GroupCipher;
603
604				if (pAd->StaCfg.WepStatus ==
605				    pAd->ScanTab.BssEntry[BssIdx].WPA.
606				    PairCipher)
607					pAd->StaCfg.PairCipher =
608					    pAd->ScanTab.BssEntry[BssIdx].WPA.
609					    PairCipher;
610				else if (pAd->ScanTab.BssEntry[BssIdx].WPA.
611					 PairCipherAux != Ndis802_11WEPDisabled)
612					pAd->StaCfg.PairCipher =
613					    pAd->ScanTab.BssEntry[BssIdx].WPA.
614					    PairCipherAux;
615				else	/* There is no PairCipher Aux, downgrade our capability to TKIP */
616					pAd->StaCfg.PairCipher =
617					    Ndis802_11Encryption2Enabled;
618			} else
619			    if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2)
620				|| (pAd->StaCfg.AuthMode ==
621				    Ndis802_11AuthModeWPA2PSK)) {
622				pAd->StaCfg.GroupCipher =
623				    pAd->ScanTab.BssEntry[BssIdx].WPA2.
624				    GroupCipher;
625
626				if (pAd->StaCfg.WepStatus ==
627				    pAd->ScanTab.BssEntry[BssIdx].WPA2.
628				    PairCipher)
629					pAd->StaCfg.PairCipher =
630					    pAd->ScanTab.BssEntry[BssIdx].WPA2.
631					    PairCipher;
632				else if (pAd->ScanTab.BssEntry[BssIdx].WPA2.
633					 PairCipherAux != Ndis802_11WEPDisabled)
634					pAd->StaCfg.PairCipher =
635					    pAd->ScanTab.BssEntry[BssIdx].WPA2.
636					    PairCipherAux;
637				else	/* There is no PairCipher Aux, downgrade our capability to TKIP */
638					pAd->StaCfg.PairCipher =
639					    Ndis802_11Encryption2Enabled;
640
641				/* RSN capability */
642				pAd->StaCfg.RsnCapability =
643				    pAd->ScanTab.BssEntry[BssIdx].WPA2.
644				    RsnCapability;
645			}
646			/* Set Mix cipher flag */
647			pAd->StaCfg.bMixCipher =
648			    (pAd->StaCfg.PairCipher ==
649			     pAd->StaCfg.GroupCipher) ? FALSE : TRUE;
650			/*if (pAd->StaCfg.bMixCipher == TRUE)
651			   {
652			   // If mix cipher, re-build RSNIE
653			   RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, 0);
654			   } */
655			/* No active association, join the BSS immediately */
656			DBGPRINT(RT_DEBUG_TRACE,
657				 ("CNTL - joining %02x:%02x:%02x:%02x:%02x:%02x ...\n",
658				  pOidBssid[0], pOidBssid[1], pOidBssid[2],
659				  pOidBssid[3], pOidBssid[4], pOidBssid[5]));
660
661			JoinParmFill(pAd, &JoinReq, pAd->MlmeAux.BssIdx);
662			MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_JOIN_REQ,
663				    sizeof(struct rt_mlme_join_req), &JoinReq);
664
665			pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_JOIN;
666		}
667	}
668}
669
670/* Roaming is the only external request triggering CNTL state machine */
671/* despite of other "SET OID" operation. All "SET OID" related oerations */
672/* happen in sequence, because no other SET OID will be sent to this device */
673/* until the the previous SET operation is complete (successful o failed). */
674/* So, how do we quarantee this ROAMING request won't corrupt other "SET OID"? */
675/* or been corrupted by other "SET OID"? */
676/* */
677/* IRQL = DISPATCH_LEVEL */
678void CntlMlmeRoamingProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
679{
680	u8 BBPValue = 0;
681
682	DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Roaming in MlmeAux.RoamTab...\n"));
683
684	{
685		/*Let BBP register at 20MHz to do (fast) roaming. */
686		RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
687		BBPValue &= (~0x18);
688		RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
689
690		NdisMoveMemory(&pAd->MlmeAux.SsidBssTab, &pAd->MlmeAux.RoamTab,
691			       sizeof(pAd->MlmeAux.RoamTab));
692		pAd->MlmeAux.SsidBssTab.BssNr = pAd->MlmeAux.RoamTab.BssNr;
693
694		BssTableSortByRssi(&pAd->MlmeAux.SsidBssTab);
695		pAd->MlmeAux.BssIdx = 0;
696		IterateOnBssTab(pAd);
697	}
698}
699
700/*
701	==========================================================================
702	Description:
703
704	IRQL = DISPATCH_LEVEL
705
706	==========================================================================
707*/
708void CntlWaitDisassocProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
709{
710	struct rt_mlme_start_req StartReq;
711
712	if (Elem->MsgType == MT2_DISASSOC_CONF) {
713		DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Dis-associate successful\n"));
714
715		if (pAd->CommonCfg.bWirelessEvent) {
716			RTMPSendWirelessEvent(pAd, IW_DISASSOC_EVENT_FLAG,
717					      pAd->MacTab.Content[BSSID_WCID].
718					      Addr, BSS0, 0);
719		}
720
721		LinkDown(pAd, FALSE);
722
723		/* case 1. no matching BSS, and user wants ADHOC, so we just start a new one */
724		if ((pAd->MlmeAux.SsidBssTab.BssNr == 0)
725		    && (pAd->StaCfg.BssType == BSS_ADHOC)) {
726			DBGPRINT(RT_DEBUG_TRACE,
727				 ("CNTL - No matching BSS, start a new ADHOC (Ssid=%s)...\n",
728				  pAd->MlmeAux.Ssid));
729			StartParmFill(pAd, &StartReq, (char *)pAd->MlmeAux.Ssid,
730				      pAd->MlmeAux.SsidLen);
731			MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ,
732				    sizeof(struct rt_mlme_start_req), &StartReq);
733			pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
734		}
735		/* case 2. try each matched BSS */
736		else {
737			pAd->MlmeAux.BssIdx = 0;
738
739			IterateOnBssTab(pAd);
740		}
741	}
742}
743
744/*
745	==========================================================================
746	Description:
747
748	IRQL = DISPATCH_LEVEL
749
750	==========================================================================
751*/
752void CntlWaitJoinProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
753{
754	u16 Reason;
755	struct rt_mlme_auth_req AuthReq;
756
757	if (Elem->MsgType == MT2_JOIN_CONF) {
758		NdisMoveMemory(&Reason, Elem->Msg, sizeof(u16));
759		if (Reason == MLME_SUCCESS) {
760			/* 1. joined an IBSS, we are pretty much done here */
761			if (pAd->MlmeAux.BssType == BSS_ADHOC) {
762				/* */
763				/* 5G bands rules of Japan: */
764				/* Ad hoc must be disabled in W53(ch52,56,60,64) channels. */
765				/* */
766				if ((pAd->CommonCfg.bIEEE80211H == 1) &&
767				    RadarChannelCheck(pAd,
768						      pAd->CommonCfg.Channel)
769				    ) {
770					pAd->Mlme.CntlMachine.CurrState =
771					    CNTL_IDLE;
772					DBGPRINT(RT_DEBUG_TRACE,
773						 ("CNTL - Channel=%d, Join adhoc on W53(52,56,60,64) Channels are not accepted\n",
774						  pAd->CommonCfg.Channel));
775					return;
776				}
777
778				LinkUp(pAd, BSS_ADHOC);
779				pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
780				DBGPRINT(RT_DEBUG_TRACE,
781					 ("CNTL - join the IBSS = %02x:%02x:%02x:%02x:%02x:%02x ...\n",
782					  pAd->CommonCfg.Bssid[0],
783					  pAd->CommonCfg.Bssid[1],
784					  pAd->CommonCfg.Bssid[2],
785					  pAd->CommonCfg.Bssid[3],
786					  pAd->CommonCfg.Bssid[4],
787					  pAd->CommonCfg.Bssid[5]));
788
789				pAd->IndicateMediaState =
790				    NdisMediaStateConnected;
791				pAd->ExtraInfo = GENERAL_LINK_UP;
792			}
793			/* 2. joined a new INFRA network, start from authentication */
794			else {
795				{
796					/* either Ndis802_11AuthModeShared or Ndis802_11AuthModeAutoSwitch, try shared key first */
797					if ((pAd->StaCfg.AuthMode ==
798					     Ndis802_11AuthModeShared)
799					    || (pAd->StaCfg.AuthMode ==
800						Ndis802_11AuthModeAutoSwitch)) {
801						AuthParmFill(pAd, &AuthReq,
802							     pAd->MlmeAux.Bssid,
803							     AUTH_MODE_KEY);
804					} else {
805						AuthParmFill(pAd, &AuthReq,
806							     pAd->MlmeAux.Bssid,
807							     AUTH_MODE_OPEN);
808					}
809					MlmeEnqueue(pAd, AUTH_STATE_MACHINE,
810						    MT2_MLME_AUTH_REQ,
811						    sizeof
812						    (struct rt_mlme_auth_req),
813						    &AuthReq);
814				}
815
816				pAd->Mlme.CntlMachine.CurrState =
817				    CNTL_WAIT_AUTH;
818			}
819		} else {
820			/* 3. failed, try next BSS */
821			pAd->MlmeAux.BssIdx++;
822			IterateOnBssTab(pAd);
823		}
824	}
825}
826
827/*
828	==========================================================================
829	Description:
830
831	IRQL = DISPATCH_LEVEL
832
833	==========================================================================
834*/
835void CntlWaitStartProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
836{
837	u16 Result;
838
839	if (Elem->MsgType == MT2_START_CONF) {
840		NdisMoveMemory(&Result, Elem->Msg, sizeof(u16));
841		if (Result == MLME_SUCCESS) {
842			/* */
843			/* 5G bands rules of Japan: */
844			/* Ad hoc must be disabled in W53(ch52,56,60,64) channels. */
845			/* */
846			if ((pAd->CommonCfg.bIEEE80211H == 1) &&
847			    RadarChannelCheck(pAd, pAd->CommonCfg.Channel)
848			    ) {
849				pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
850				DBGPRINT(RT_DEBUG_TRACE,
851					 ("CNTL - Channel=%d, Start adhoc on W53(52,56,60,64) Channels are not accepted\n",
852					  pAd->CommonCfg.Channel));
853				return;
854			}
855			NdisZeroMemory(&pAd->StaActive.SupportedPhyInfo.
856				       MCSSet[0], 16);
857			if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) {
858				N_ChannelCheck(pAd);
859				SetCommonHT(pAd);
860				NdisMoveMemory(&pAd->MlmeAux.AddHtInfo,
861					       &pAd->CommonCfg.AddHTInfo,
862					       sizeof(struct rt_add_ht_info_ie));
863				RTMPCheckHt(pAd, BSSID_WCID,
864					    &pAd->CommonCfg.HtCapability,
865					    &pAd->CommonCfg.AddHTInfo);
866				pAd->StaActive.SupportedPhyInfo.bHtEnable =
867				    TRUE;
868				NdisMoveMemory(&pAd->StaActive.SupportedPhyInfo.
869					       MCSSet[0],
870					       &pAd->CommonCfg.HtCapability.
871					       MCSSet[0], 16);
872				COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG
873				    (pAd);
874
875				if ((pAd->CommonCfg.HtCapability.HtCapInfo.
876				     ChannelWidth == BW_40)
877				    && (pAd->CommonCfg.AddHTInfo.AddHtInfo.
878					ExtChanOffset == EXTCHA_ABOVE)) {
879					pAd->MlmeAux.CentralChannel =
880					    pAd->CommonCfg.Channel + 2;
881				} else
882				    if ((pAd->CommonCfg.HtCapability.HtCapInfo.
883					 ChannelWidth == BW_40)
884					&& (pAd->CommonCfg.AddHTInfo.AddHtInfo.
885					    ExtChanOffset == EXTCHA_BELOW)) {
886					pAd->MlmeAux.CentralChannel =
887					    pAd->CommonCfg.Channel - 2;
888				}
889			} else {
890				pAd->StaActive.SupportedPhyInfo.bHtEnable =
891				    FALSE;
892			}
893			LinkUp(pAd, BSS_ADHOC);
894			pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
895			/* Before send beacon, driver need do radar detection */
896			if ((pAd->CommonCfg.Channel > 14)
897			    && (pAd->CommonCfg.bIEEE80211H == 1)
898			    && RadarChannelCheck(pAd, pAd->CommonCfg.Channel)) {
899				pAd->CommonCfg.RadarDetect.RDMode =
900				    RD_SILENCE_MODE;
901				pAd->CommonCfg.RadarDetect.RDCount = 0;
902			}
903
904			DBGPRINT(RT_DEBUG_TRACE,
905				 ("CNTL - start a new IBSS = %02x:%02x:%02x:%02x:%02x:%02x ...\n",
906				  pAd->CommonCfg.Bssid[0],
907				  pAd->CommonCfg.Bssid[1],
908				  pAd->CommonCfg.Bssid[2],
909				  pAd->CommonCfg.Bssid[3],
910				  pAd->CommonCfg.Bssid[4],
911				  pAd->CommonCfg.Bssid[5]));
912		} else {
913			DBGPRINT(RT_DEBUG_TRACE,
914				 ("CNTL - Start IBSS fail. BUG!\n"));
915			pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
916		}
917	}
918}
919
920/*
921	==========================================================================
922	Description:
923
924	IRQL = DISPATCH_LEVEL
925
926	==========================================================================
927*/
928void CntlWaitAuthProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
929{
930	u16 Reason;
931	struct rt_mlme_assoc_req AssocReq;
932	struct rt_mlme_auth_req AuthReq;
933
934	if (Elem->MsgType == MT2_AUTH_CONF) {
935		NdisMoveMemory(&Reason, Elem->Msg, sizeof(u16));
936		if (Reason == MLME_SUCCESS) {
937			DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH OK\n"));
938			AssocParmFill(pAd, &AssocReq, pAd->MlmeAux.Bssid,
939				      pAd->MlmeAux.CapabilityInfo,
940				      ASSOC_TIMEOUT,
941				      pAd->StaCfg.DefaultListenCount);
942
943			{
944				MlmeEnqueue(pAd, ASSOC_STATE_MACHINE,
945					    MT2_MLME_ASSOC_REQ,
946					    sizeof(struct rt_mlme_assoc_req),
947					    &AssocReq);
948
949				pAd->Mlme.CntlMachine.CurrState =
950				    CNTL_WAIT_ASSOC;
951			}
952		} else {
953			/* This fail may because of the AP already keep us in its MAC table without */
954			/* ageing-out. The previous authentication attempt must have let it remove us. */
955			/* so try Authentication again may help. For D-Link DWL-900AP+ compatibility. */
956			DBGPRINT(RT_DEBUG_TRACE,
957				 ("CNTL - AUTH FAIL, try again...\n"));
958
959			{
960				if ((pAd->StaCfg.AuthMode ==
961				     Ndis802_11AuthModeShared)
962				    || (pAd->StaCfg.AuthMode ==
963					Ndis802_11AuthModeAutoSwitch)) {
964					/* either Ndis802_11AuthModeShared or Ndis802_11AuthModeAutoSwitch, try shared key first */
965					AuthParmFill(pAd, &AuthReq,
966						     pAd->MlmeAux.Bssid,
967						     AUTH_MODE_KEY);
968				} else {
969					AuthParmFill(pAd, &AuthReq,
970						     pAd->MlmeAux.Bssid,
971						     AUTH_MODE_OPEN);
972				}
973				MlmeEnqueue(pAd, AUTH_STATE_MACHINE,
974					    MT2_MLME_AUTH_REQ,
975					    sizeof(struct rt_mlme_auth_req),
976					    &AuthReq);
977
978			}
979			pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_AUTH2;
980		}
981	}
982}
983
984/*
985	==========================================================================
986	Description:
987
988	IRQL = DISPATCH_LEVEL
989
990	==========================================================================
991*/
992void CntlWaitAuthProc2(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
993{
994	u16 Reason;
995	struct rt_mlme_assoc_req AssocReq;
996	struct rt_mlme_auth_req AuthReq;
997
998	if (Elem->MsgType == MT2_AUTH_CONF) {
999		NdisMoveMemory(&Reason, Elem->Msg, sizeof(u16));
1000		if (Reason == MLME_SUCCESS) {
1001			DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH OK\n"));
1002			AssocParmFill(pAd, &AssocReq, pAd->MlmeAux.Bssid,
1003				      pAd->MlmeAux.CapabilityInfo,
1004				      ASSOC_TIMEOUT,
1005				      pAd->StaCfg.DefaultListenCount);
1006			{
1007				MlmeEnqueue(pAd, ASSOC_STATE_MACHINE,
1008					    MT2_MLME_ASSOC_REQ,
1009					    sizeof(struct rt_mlme_assoc_req),
1010					    &AssocReq);
1011
1012				pAd->Mlme.CntlMachine.CurrState =
1013				    CNTL_WAIT_ASSOC;
1014			}
1015		} else {
1016			if ((pAd->StaCfg.AuthMode ==
1017			     Ndis802_11AuthModeAutoSwitch)
1018			    && (pAd->MlmeAux.Alg == Ndis802_11AuthModeShared)) {
1019				DBGPRINT(RT_DEBUG_TRACE,
1020					 ("CNTL - AUTH FAIL, try OPEN system...\n"));
1021				AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid,
1022					     Ndis802_11AuthModeOpen);
1023				MlmeEnqueue(pAd, AUTH_STATE_MACHINE,
1024					    MT2_MLME_AUTH_REQ,
1025					    sizeof(struct rt_mlme_auth_req),
1026					    &AuthReq);
1027
1028				pAd->Mlme.CntlMachine.CurrState =
1029				    CNTL_WAIT_AUTH2;
1030			} else {
1031				/* not success, try next BSS */
1032				DBGPRINT(RT_DEBUG_TRACE,
1033					 ("CNTL - AUTH FAIL, give up; try next BSS\n"));
1034				pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;	/*??????? */
1035				pAd->MlmeAux.BssIdx++;
1036				IterateOnBssTab(pAd);
1037			}
1038		}
1039	}
1040}
1041
1042/*
1043	==========================================================================
1044	Description:
1045
1046	IRQL = DISPATCH_LEVEL
1047
1048	==========================================================================
1049*/
1050void CntlWaitAssocProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
1051{
1052	u16 Reason;
1053
1054	if (Elem->MsgType == MT2_ASSOC_CONF) {
1055		NdisMoveMemory(&Reason, Elem->Msg, sizeof(u16));
1056		if (Reason == MLME_SUCCESS) {
1057			if (pAd->CommonCfg.bWirelessEvent) {
1058				RTMPSendWirelessEvent(pAd, IW_ASSOC_EVENT_FLAG,
1059						      pAd->MacTab.
1060						      Content[BSSID_WCID].Addr,
1061						      BSS0, 0);
1062			}
1063
1064			LinkUp(pAd, BSS_INFRA);
1065			pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
1066			DBGPRINT(RT_DEBUG_TRACE,
1067				 ("CNTL - Association successful on BSS #%ld\n",
1068				  pAd->MlmeAux.BssIdx));
1069		} else {
1070			/* not success, try next BSS */
1071			DBGPRINT(RT_DEBUG_TRACE,
1072				 ("CNTL - Association fails on BSS #%ld\n",
1073				  pAd->MlmeAux.BssIdx));
1074			pAd->MlmeAux.BssIdx++;
1075			IterateOnBssTab(pAd);
1076		}
1077	}
1078}
1079
1080/*
1081	==========================================================================
1082	Description:
1083
1084	IRQL = DISPATCH_LEVEL
1085
1086	==========================================================================
1087*/
1088void CntlWaitReassocProc(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
1089{
1090	u16 Result;
1091
1092	if (Elem->MsgType == MT2_REASSOC_CONF) {
1093		NdisMoveMemory(&Result, Elem->Msg, sizeof(u16));
1094		if (Result == MLME_SUCCESS) {
1095			/* send wireless event - for association */
1096			if (pAd->CommonCfg.bWirelessEvent)
1097				RTMPSendWirelessEvent(pAd, IW_ASSOC_EVENT_FLAG,
1098						      pAd->MacTab.
1099						      Content[BSSID_WCID].Addr,
1100						      BSS0, 0);
1101
1102			/* */
1103			/* NDIS requires a new Link UP indication but no Link Down for RE-ASSOC */
1104			/* */
1105			LinkUp(pAd, BSS_INFRA);
1106
1107			pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
1108			DBGPRINT(RT_DEBUG_TRACE,
1109				 ("CNTL - Re-assocition successful on BSS #%ld\n",
1110				  pAd->MlmeAux.RoamIdx));
1111		} else {
1112			/* reassoc failed, try to pick next BSS in the BSS Table */
1113			DBGPRINT(RT_DEBUG_TRACE,
1114				 ("CNTL - Re-assocition fails on BSS #%ld\n",
1115				  pAd->MlmeAux.RoamIdx));
1116			{
1117				pAd->MlmeAux.RoamIdx++;
1118				IterateOnBssTab2(pAd);
1119			}
1120		}
1121	}
1122}
1123
1124void AdhocTurnOnQos(struct rt_rtmp_adapter *pAd)
1125{
1126#define AC0_DEF_TXOP		0
1127#define AC1_DEF_TXOP		0
1128#define AC2_DEF_TXOP		94
1129#define AC3_DEF_TXOP		47
1130
1131	/* Turn on QOs if use HT rate. */
1132	if (pAd->CommonCfg.APEdcaParm.bValid == FALSE) {
1133		pAd->CommonCfg.APEdcaParm.bValid = TRUE;
1134		pAd->CommonCfg.APEdcaParm.Aifsn[0] = 3;
1135		pAd->CommonCfg.APEdcaParm.Aifsn[1] = 7;
1136		pAd->CommonCfg.APEdcaParm.Aifsn[2] = 1;
1137		pAd->CommonCfg.APEdcaParm.Aifsn[3] = 1;
1138
1139		pAd->CommonCfg.APEdcaParm.Cwmin[0] = 4;
1140		pAd->CommonCfg.APEdcaParm.Cwmin[1] = 4;
1141		pAd->CommonCfg.APEdcaParm.Cwmin[2] = 3;
1142		pAd->CommonCfg.APEdcaParm.Cwmin[3] = 2;
1143
1144		pAd->CommonCfg.APEdcaParm.Cwmax[0] = 10;
1145		pAd->CommonCfg.APEdcaParm.Cwmax[1] = 6;
1146		pAd->CommonCfg.APEdcaParm.Cwmax[2] = 4;
1147		pAd->CommonCfg.APEdcaParm.Cwmax[3] = 3;
1148
1149		pAd->CommonCfg.APEdcaParm.Txop[0] = 0;
1150		pAd->CommonCfg.APEdcaParm.Txop[1] = 0;
1151		pAd->CommonCfg.APEdcaParm.Txop[2] = AC2_DEF_TXOP;
1152		pAd->CommonCfg.APEdcaParm.Txop[3] = AC3_DEF_TXOP;
1153	}
1154	AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm);
1155}
1156
1157/*
1158	==========================================================================
1159	Description:
1160
1161	IRQL = DISPATCH_LEVEL
1162
1163	==========================================================================
1164*/
1165void LinkUp(struct rt_rtmp_adapter *pAd, u8 BssType)
1166{
1167	unsigned long Now;
1168	u32 Data;
1169	BOOLEAN Cancelled;
1170	u8 Value = 0, idx = 0, HashIdx = 0;
1171	struct rt_mac_table_entry *pEntry = NULL, *pCurrEntry = NULL;
1172
1173	/* Init ChannelQuality to prevent DEAD_CQI at initial LinkUp */
1174	pAd->Mlme.ChannelQuality = 50;
1175
1176	pEntry = MacTableLookup(pAd, pAd->CommonCfg.Bssid);
1177	if (pEntry) {
1178		MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr);
1179		pEntry = NULL;
1180	}
1181
1182	pEntry = &pAd->MacTab.Content[BSSID_WCID];
1183
1184	/* */
1185	/* ASSOC - DisassocTimeoutAction */
1186	/* CNTL - Dis-associate successful */
1187	/* ! LINK DOWN ! */
1188	/* [88888] OID_802_11_SSID should have returned NDTEST_WEP_AP2(Returned: ) */
1189	/* */
1190	/* To prevent DisassocTimeoutAction to call Link down after we link up, */
1191	/* cancel the DisassocTimer no matter what it start or not. */
1192	/* */
1193	RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
1194
1195	COPY_SETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd);
1196
1197	COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd);
1198
1199#ifdef RTMP_MAC_PCI
1200	/* Before power save before link up function, We will force use 1R. */
1201	/* So after link up, check Rx antenna # again. */
1202	RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value);
1203	if (pAd->Antenna.field.RxPath == 3) {
1204		Value |= (0x10);
1205	} else if (pAd->Antenna.field.RxPath == 2) {
1206		Value |= (0x8);
1207	} else if (pAd->Antenna.field.RxPath == 1) {
1208		Value |= (0x0);
1209	}
1210	RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value);
1211	pAd->StaCfg.BBPR3 = Value;
1212#endif /* RTMP_MAC_PCI // */
1213
1214	if (BssType == BSS_ADHOC) {
1215		OPSTATUS_SET_FLAG(pAd, fOP_STATUS_ADHOC_ON);
1216		OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON);
1217
1218		if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
1219			AdhocTurnOnQos(pAd);
1220
1221		DBGPRINT(RT_DEBUG_TRACE, ("Adhoc LINK UP!\n"));
1222	} else {
1223		OPSTATUS_SET_FLAG(pAd, fOP_STATUS_INFRA_ON);
1224		OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON);
1225
1226		DBGPRINT(RT_DEBUG_TRACE, ("Infra LINK UP!\n"));
1227	}
1228
1229	/* 3*3 */
1230	/* reset Tx beamforming bit */
1231	RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value);
1232	Value &= (~0x01);
1233	Value |= pAd->CommonCfg.RegTransmitSetting.field.TxBF;
1234	RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value);
1235
1236	/* Change to AP channel */
1237	if ((pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel)
1238	    && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) {
1239		/* Must using 40MHz. */
1240		pAd->CommonCfg.BBPCurrentBW = BW_40;
1241		AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
1242		AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
1243
1244		RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value);
1245		Value &= (~0x18);
1246		Value |= 0x10;
1247		RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value);
1248
1249		/*  RX : control channel at lower */
1250		RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value);
1251		Value &= (~0x20);
1252		RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value);
1253#ifdef RTMP_MAC_PCI
1254		pAd->StaCfg.BBPR3 = Value;
1255#endif /* RTMP_MAC_PCI // */
1256
1257		RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data);
1258		Data &= 0xfffffffe;
1259		RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data);
1260
1261		if (pAd->MACVersion == 0x28600100) {
1262			RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x1A);
1263			RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A);
1264			RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x16);
1265			DBGPRINT(RT_DEBUG_TRACE, ("rt2860C !\n"));
1266		}
1267
1268		DBGPRINT(RT_DEBUG_TRACE,
1269			 ("40MHz Lower LINK UP! Control Channel at Below. Central = %d \n",
1270			  pAd->CommonCfg.CentralChannel));
1271	} else if ((pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel)
1272		   && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth ==
1273		       BW_40)) {
1274		/* Must using 40MHz. */
1275		pAd->CommonCfg.BBPCurrentBW = BW_40;
1276		AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
1277		AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
1278
1279		RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value);
1280		Value &= (~0x18);
1281		Value |= 0x10;
1282		RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value);
1283
1284		RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data);
1285		Data |= 0x1;
1286		RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data);
1287
1288		RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value);
1289		Value |= (0x20);
1290		RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value);
1291#ifdef RTMP_MAC_PCI
1292		pAd->StaCfg.BBPR3 = Value;
1293#endif /* RTMP_MAC_PCI // */
1294
1295		if (pAd->MACVersion == 0x28600100) {
1296			RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x1A);
1297			RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A);
1298			RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x16);
1299			DBGPRINT(RT_DEBUG_TRACE, ("rt2860C !\n"));
1300		}
1301
1302		DBGPRINT(RT_DEBUG_TRACE,
1303			 ("40MHz Upper LINK UP! Control Channel at UpperCentral = %d \n",
1304			  pAd->CommonCfg.CentralChannel));
1305	} else {
1306		pAd->CommonCfg.BBPCurrentBW = BW_20;
1307		pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel;
1308		AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
1309		AsicLockChannel(pAd, pAd->CommonCfg.Channel);
1310
1311		RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value);
1312		Value &= (~0x18);
1313		RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value);
1314
1315		RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data);
1316		Data &= 0xfffffffe;
1317		RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data);
1318
1319		RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value);
1320		Value &= (~0x20);
1321		RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value);
1322#ifdef RTMP_MAC_PCI
1323		pAd->StaCfg.BBPR3 = Value;
1324#endif /* RTMP_MAC_PCI // */
1325
1326		if (pAd->MACVersion == 0x28600100) {
1327			RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16);
1328			RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x08);
1329			RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x11);
1330			DBGPRINT(RT_DEBUG_TRACE, ("rt2860C !\n"));
1331		}
1332
1333		DBGPRINT(RT_DEBUG_TRACE, ("20MHz LINK UP!\n"));
1334	}
1335
1336	RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
1337
1338	/* */
1339	/* Save BBP_R66 value, it will be used in RTUSBResumeMsduTransmission */
1340	/* */
1341	RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66,
1342				    &pAd->BbpTuning.R66CurrentValue);
1343
1344	DBGPRINT(RT_DEBUG_TRACE,
1345		 ("LINK UP! (BssType=%d, AID=%d, ssid=%s, Channel=%d, CentralChannel = %d)\n",
1346		  BssType, pAd->StaActive.Aid, pAd->CommonCfg.Ssid,
1347		  pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel));
1348
1349	DBGPRINT(RT_DEBUG_TRACE,
1350		 ("LINK UP! (Density =%d, )\n",
1351		  pAd->MacTab.Content[BSSID_WCID].MpduDensity));
1352
1353	AsicSetBssid(pAd, pAd->CommonCfg.Bssid);
1354
1355	AsicSetSlotTime(pAd, TRUE);
1356	AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm);
1357
1358	/* Call this for RTS protectionfor legacy rate, we will always enable RTS threshold, but normally it will not hit */
1359	AsicUpdateProtect(pAd, 0, (OFDMSETPROTECT | CCKSETPROTECT), TRUE,
1360			  FALSE);
1361
1362	if ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE)) {
1363		/* Update HT protectionfor based on AP's operating mode. */
1364		if (pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1) {
1365			AsicUpdateProtect(pAd,
1366					  pAd->MlmeAux.AddHtInfo.AddHtInfo2.
1367					  OperaionMode, ALLN_SETPROTECT, FALSE,
1368					  TRUE);
1369		} else
1370			AsicUpdateProtect(pAd,
1371					  pAd->MlmeAux.AddHtInfo.AddHtInfo2.
1372					  OperaionMode, ALLN_SETPROTECT, FALSE,
1373					  FALSE);
1374	}
1375
1376	NdisZeroMemory(&pAd->DrsCounters, sizeof(struct rt_counter_drs));
1377
1378	NdisGetSystemUpTime(&Now);
1379	pAd->StaCfg.LastBeaconRxTime = Now;	/* last RX timestamp */
1380
1381	if ((pAd->CommonCfg.TxPreamble != Rt802_11PreambleLong) &&
1382	    CAP_IS_SHORT_PREAMBLE_ON(pAd->StaActive.CapabilityInfo)) {
1383		MlmeSetTxPreamble(pAd, Rt802_11PreambleShort);
1384	}
1385
1386	OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
1387
1388	if (pAd->CommonCfg.RadarDetect.RDMode == RD_SILENCE_MODE) {
1389	}
1390	pAd->CommonCfg.RadarDetect.RDMode = RD_NORMAL_MODE;
1391
1392	if (BssType == BSS_ADHOC) {
1393		MakeIbssBeacon(pAd);
1394		if ((pAd->CommonCfg.Channel > 14)
1395		    && (pAd->CommonCfg.bIEEE80211H == 1)
1396		    && RadarChannelCheck(pAd, pAd->CommonCfg.Channel)) {
1397			;	/*Do nothing */
1398		} else {
1399			AsicEnableIbssSync(pAd);
1400		}
1401
1402		/* In ad hoc mode, use MAC table from index 1. */
1403		/* p.s ASIC use all 0xff as termination of WCID table search.To prevent it's 0xff-ff-ff-ff-ff-ff, Write 0 here. */
1404		RTMP_IO_WRITE32(pAd, MAC_WCID_BASE, 0x00);
1405		RTMP_IO_WRITE32(pAd, 0x1808, 0x00);
1406
1407		/* If WEP is enabled, add key material and cipherAlg into Asic */
1408		/* Fill in Shared Key Table(offset: 0x6c00) and Shared Key Mode(offset: 0x7000) */
1409
1410		if (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) {
1411			u8 *Key;
1412			u8 CipherAlg;
1413
1414			for (idx = 0; idx < SHARE_KEY_NUM; idx++) {
1415				CipherAlg = pAd->SharedKey[BSS0][idx].CipherAlg;
1416				Key = pAd->SharedKey[BSS0][idx].Key;
1417
1418				if (pAd->SharedKey[BSS0][idx].KeyLen > 0) {
1419					/* Set key material and cipherAlg to Asic */
1420					AsicAddSharedKeyEntry(pAd, BSS0, idx,
1421							      CipherAlg, Key,
1422							      NULL, NULL);
1423
1424					if (idx == pAd->StaCfg.DefaultKeyId) {
1425						/* Update WCID attribute table and IVEIV table for this group key table */
1426						RTMPAddWcidAttributeEntry(pAd,
1427									  BSS0,
1428									  idx,
1429									  CipherAlg,
1430									  NULL);
1431					}
1432				}
1433
1434			}
1435		}
1436		/* If WPANone is enabled, add key material and cipherAlg into Asic */
1437		/* Fill in Shared Key Table(offset: 0x6c00) and Shared Key Mode(offset: 0x7000) */
1438		else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) {
1439			pAd->StaCfg.DefaultKeyId = 0;	/* always be zero */
1440
1441			NdisZeroMemory(&pAd->SharedKey[BSS0][0],
1442				       sizeof(struct rt_cipher_key));
1443			pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK;
1444			NdisMoveMemory(pAd->SharedKey[BSS0][0].Key,
1445				       pAd->StaCfg.PMK, LEN_TKIP_EK);
1446
1447			if (pAd->StaCfg.PairCipher ==
1448			    Ndis802_11Encryption2Enabled) {
1449				NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic,
1450					       &pAd->StaCfg.PMK[16],
1451					       LEN_TKIP_RXMICK);
1452				NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic,
1453					       &pAd->StaCfg.PMK[16],
1454					       LEN_TKIP_TXMICK);
1455			}
1456			/* Decide its ChiperAlg */
1457			if (pAd->StaCfg.PairCipher ==
1458			    Ndis802_11Encryption2Enabled)
1459				pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP;
1460			else if (pAd->StaCfg.PairCipher ==
1461				 Ndis802_11Encryption3Enabled)
1462				pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES;
1463			else {
1464				DBGPRINT(RT_DEBUG_TRACE,
1465					 ("Unknow Cipher (=%d), set Cipher to AES\n",
1466					  pAd->StaCfg.PairCipher));
1467				pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES;
1468			}
1469
1470			/* Set key material and cipherAlg to Asic */
1471			AsicAddSharedKeyEntry(pAd,
1472					      BSS0,
1473					      0,
1474					      pAd->SharedKey[BSS0][0].CipherAlg,
1475					      pAd->SharedKey[BSS0][0].Key,
1476					      pAd->SharedKey[BSS0][0].TxMic,
1477					      pAd->SharedKey[BSS0][0].RxMic);
1478
1479			/* Update WCID attribute table and IVEIV table for this group key table */
1480			RTMPAddWcidAttributeEntry(pAd, BSS0, 0,
1481						  pAd->SharedKey[BSS0][0].
1482						  CipherAlg, NULL);
1483
1484		}
1485
1486	} else			/* BSS_INFRA */
1487	{
1488		/* Check the new SSID with last SSID */
1489		while (Cancelled == TRUE) {
1490			if (pAd->CommonCfg.LastSsidLen ==
1491			    pAd->CommonCfg.SsidLen) {
1492				if (RTMPCompareMemory
1493				    (pAd->CommonCfg.LastSsid,
1494				     pAd->CommonCfg.Ssid,
1495				     pAd->CommonCfg.LastSsidLen) == 0) {
1496					/* Link to the old one no linkdown is required. */
1497					break;
1498				}
1499			}
1500			/* Send link down event before set to link up */
1501			pAd->IndicateMediaState = NdisMediaStateDisconnected;
1502			RTMP_IndicateMediaState(pAd);
1503			pAd->ExtraInfo = GENERAL_LINK_DOWN;
1504			DBGPRINT(RT_DEBUG_TRACE,
1505				 ("NDIS_STATUS_MEDIA_DISCONNECT Event AA!\n"));
1506			break;
1507		}
1508
1509		/* */
1510		/* On WPA mode, Remove All Keys if not connect to the last BSSID */
1511		/* Key will be set after 4-way handshake. */
1512		/* */
1513		if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) {
1514			unsigned long IV;
1515
1516			/* Remove all WPA keys */
1517			RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
1518			RTMPWPARemoveAllKeys(pAd);
1519			pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
1520			pAd->StaCfg.PrivacyFilter =
1521			    Ndis802_11PrivFilter8021xWEP;
1522
1523			/* Fixed connection failed with Range Maximizer - 515 AP (Marvell Chip) when security is WPAPSK/TKIP */
1524			/* If IV related values are too large in GroupMsg2, AP would ignore this message. */
1525			IV = 1;
1526			IV |= (pAd->StaCfg.DefaultKeyId << 30);
1527			AsicUpdateWCIDIVEIV(pAd, BSSID_WCID, IV, 0);
1528		}
1529		/* NOTE: */
1530		/* the decision of using "short slot time" or not may change dynamically due to */
1531		/* new STA association to the AP. so we have to decide that upon parsing BEACON, not here */
1532
1533		/* NOTE: */
1534		/* the decision to use "RTC/CTS" or "CTS-to-self" protection or not may change dynamically */
1535		/* due to new STA association to the AP. so we have to decide that upon parsing BEACON, not here */
1536
1537		ComposePsPoll(pAd);
1538		ComposeNullFrame(pAd);
1539
1540		AsicEnableBssSync(pAd);
1541
1542		/* Add BSSID to WCID search table */
1543		AsicUpdateRxWCIDTable(pAd, BSSID_WCID, pAd->CommonCfg.Bssid);
1544
1545		/* If WEP is enabled, add paiewise and shared key */
1546		if (((pAd->StaCfg.WpaSupplicantUP) &&
1547		     (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) &&
1548		     (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_SECURED)) ||
1549		    ((pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) &&
1550		     (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled))) {
1551			u8 *Key;
1552			u8 CipherAlg;
1553
1554			for (idx = 0; idx < SHARE_KEY_NUM; idx++) {
1555				CipherAlg = pAd->SharedKey[BSS0][idx].CipherAlg;
1556				Key = pAd->SharedKey[BSS0][idx].Key;
1557
1558				if (pAd->SharedKey[BSS0][idx].KeyLen > 0) {
1559					/* Set key material and cipherAlg to Asic */
1560					AsicAddSharedKeyEntry(pAd, BSS0, idx,
1561							      CipherAlg, Key,
1562							      NULL, NULL);
1563
1564					if (idx == pAd->StaCfg.DefaultKeyId) {
1565						/* Assign group key info */
1566						RTMPAddWcidAttributeEntry(pAd,
1567									  BSS0,
1568									  idx,
1569									  CipherAlg,
1570									  NULL);
1571
1572						pEntry->Aid = BSSID_WCID;
1573						/* Assign pairwise key info */
1574						RTMPAddWcidAttributeEntry(pAd,
1575									  BSS0,
1576									  idx,
1577									  CipherAlg,
1578									  pEntry);
1579					}
1580				}
1581			}
1582		}
1583		/* only INFRASTRUCTURE mode need to indicate connectivity immediately; ADHOC mode */
1584		/* should wait until at least 2 active nodes in this BSSID. */
1585		OPSTATUS_SET_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
1586
1587		/* For GUI ++ */
1588		if (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA) {
1589			pAd->IndicateMediaState = NdisMediaStateConnected;
1590			pAd->ExtraInfo = GENERAL_LINK_UP;
1591			RTMP_IndicateMediaState(pAd);
1592		} else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1593			   (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
1594		{
1595			if (pAd->StaCfg.WpaSupplicantUP ==
1596			    WPA_SUPPLICANT_DISABLE)
1597				RTMPSetTimer(&pAd->Mlme.LinkDownTimer,
1598					     LINK_DOWN_TIMEOUT);
1599		}
1600		/* -- */
1601
1602		/* Add BSSID in my MAC Table. */
1603		NdisAcquireSpinLock(&pAd->MacTabLock);
1604		/* add this MAC entry into HASH table */
1605		if (pEntry) {
1606			HashIdx = MAC_ADDR_HASH_INDEX(pAd->CommonCfg.Bssid);
1607			if (pAd->MacTab.Hash[HashIdx] == NULL) {
1608				pAd->MacTab.Hash[HashIdx] = pEntry;
1609			} else {
1610				pCurrEntry = pAd->MacTab.Hash[HashIdx];
1611				while (pCurrEntry->pNext != NULL) {
1612					pCurrEntry = pCurrEntry->pNext;
1613				}
1614				pCurrEntry->pNext = pEntry;
1615			}
1616		}
1617		RTMPMoveMemory(pEntry->Addr, pAd->CommonCfg.Bssid,
1618			       MAC_ADDR_LEN);
1619		pEntry->Aid = BSSID_WCID;
1620		pEntry->pAd = pAd;
1621		pEntry->ValidAsCLI = TRUE;	/*Although this is bssid..still set ValidAsCl */
1622		pAd->MacTab.Size = 1;	/* infra mode always set MACtab size =1. */
1623		pEntry->Sst = SST_ASSOC;
1624		pEntry->AuthState = SST_ASSOC;
1625		pEntry->AuthMode = pAd->StaCfg.AuthMode;
1626		pEntry->WepStatus = pAd->StaCfg.WepStatus;
1627		if (pEntry->AuthMode < Ndis802_11AuthModeWPA) {
1628			pEntry->WpaState = AS_NOTUSE;
1629			pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
1630		} else {
1631			pEntry->WpaState = AS_PTKSTART;
1632			pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP;
1633		}
1634		NdisReleaseSpinLock(&pAd->MacTabLock);
1635
1636		DBGPRINT(RT_DEBUG_TRACE,
1637			 ("LINK UP!  ClientStatusFlags=%lx)\n",
1638			  pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags));
1639
1640		MlmeUpdateTxRates(pAd, TRUE, BSS0);
1641		MlmeUpdateHtTxRates(pAd, BSS0);
1642		DBGPRINT(RT_DEBUG_TRACE,
1643			 ("LINK UP! (StaActive.bHtEnable =%d, )\n",
1644			  pAd->StaActive.SupportedPhyInfo.bHtEnable));
1645
1646		if (pAd->CommonCfg.bAggregationCapable) {
1647			if ((pAd->CommonCfg.bPiggyBackCapable)
1648			    && (pAd->MlmeAux.APRalinkIe & 0x00000003) == 3) {
1649				OPSTATUS_SET_FLAG(pAd,
1650						  fOP_STATUS_PIGGYBACK_INUSED);
1651				OPSTATUS_SET_FLAG(pAd,
1652						  fOP_STATUS_AGGREGATION_INUSED);
1653				CLIENT_STATUS_SET_FLAG(pEntry,
1654						       fCLIENT_STATUS_AGGREGATION_CAPABLE);
1655				CLIENT_STATUS_SET_FLAG(pEntry,
1656						       fCLIENT_STATUS_PIGGYBACK_CAPABLE);
1657				RTMPSetPiggyBack(pAd, TRUE);
1658				DBGPRINT(RT_DEBUG_TRACE,
1659					 ("Turn on Piggy-Back\n"));
1660			} else if (pAd->MlmeAux.APRalinkIe & 0x00000001) {
1661				OPSTATUS_SET_FLAG(pAd,
1662						  fOP_STATUS_AGGREGATION_INUSED);
1663				CLIENT_STATUS_SET_FLAG(pEntry,
1664						       fCLIENT_STATUS_AGGREGATION_CAPABLE);
1665				DBGPRINT(RT_DEBUG_TRACE,
1666					 ("Ralink Aggregation\n"));
1667			}
1668		}
1669
1670		if (pAd->MlmeAux.APRalinkIe != 0x0) {
1671			if (CLIENT_STATUS_TEST_FLAG
1672			    (pEntry, fCLIENT_STATUS_RDG_CAPABLE)) {
1673				AsicEnableRDG(pAd);
1674			}
1675			OPSTATUS_SET_FLAG(pAd, fCLIENT_STATUS_RALINK_CHIPSET);
1676			CLIENT_STATUS_SET_FLAG(pEntry,
1677					       fCLIENT_STATUS_RALINK_CHIPSET);
1678		} else {
1679			OPSTATUS_CLEAR_FLAG(pAd, fCLIENT_STATUS_RALINK_CHIPSET);
1680			CLIENT_STATUS_CLEAR_FLAG(pEntry,
1681						 fCLIENT_STATUS_RALINK_CHIPSET);
1682		}
1683	}
1684
1685	DBGPRINT(RT_DEBUG_TRACE,
1686		 ("NDIS_STATUS_MEDIA_CONNECT Event B!.BACapability = %x. ClientStatusFlags = %lx\n",
1687		  pAd->CommonCfg.BACapability.word,
1688		  pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags));
1689
1690	/* Set LED */
1691	RTMPSetLED(pAd, LED_LINK_UP);
1692
1693	pAd->Mlme.PeriodicRound = 0;
1694	pAd->Mlme.OneSecPeriodicRound = 0;
1695	pAd->bConfigChanged = FALSE;	/* Reset config flag */
1696	pAd->ExtraInfo = GENERAL_LINK_UP;	/* Update extra information to link is up */
1697
1698	/* Set asic auto fall back */
1699	{
1700		u8 *pTable;
1701		u8 TableSize = 0;
1702
1703		MlmeSelectTxRateTable(pAd, &pAd->MacTab.Content[BSSID_WCID],
1704				      &pTable, &TableSize,
1705				      &pAd->CommonCfg.TxRateIndex);
1706		AsicUpdateAutoFallBackTable(pAd, pTable);
1707	}
1708
1709	NdisAcquireSpinLock(&pAd->MacTabLock);
1710	pEntry->HTPhyMode.word = pAd->StaCfg.HTPhyMode.word;
1711	pEntry->MaxHTPhyMode.word = pAd->StaCfg.HTPhyMode.word;
1712	if (pAd->StaCfg.bAutoTxRateSwitch == FALSE) {
1713		pEntry->bAutoTxRateSwitch = FALSE;
1714
1715		if (pEntry->HTPhyMode.field.MCS == 32)
1716			pEntry->HTPhyMode.field.ShortGI = GI_800;
1717
1718		if ((pEntry->HTPhyMode.field.MCS > MCS_7)
1719		    || (pEntry->HTPhyMode.field.MCS == 32))
1720			pEntry->HTPhyMode.field.STBC = STBC_NONE;
1721
1722		/* If the legacy mode is set, overwrite the transmit setting of this entry. */
1723		if (pEntry->HTPhyMode.field.MODE <= MODE_OFDM)
1724			RTMPUpdateLegacyTxSetting((u8)pAd->StaCfg.
1725						  DesiredTransmitSetting.field.
1726						  FixedTxMode, pEntry);
1727	} else
1728		pEntry->bAutoTxRateSwitch = TRUE;
1729	NdisReleaseSpinLock(&pAd->MacTabLock);
1730
1731	/*  Let Link Status Page display first initial rate. */
1732	pAd->LastTxRate = (u16)(pEntry->HTPhyMode.word);
1733	/* Select DAC according to HT or Legacy */
1734	if (pAd->StaActive.SupportedPhyInfo.MCSSet[0] != 0x00) {
1735		RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &Value);
1736		Value &= (~0x18);
1737		if (pAd->Antenna.field.TxPath == 2) {
1738			Value |= 0x10;
1739		}
1740		RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, Value);
1741	} else {
1742		RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &Value);
1743		Value &= (~0x18);
1744		RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, Value);
1745	}
1746
1747	if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) {
1748	} else if (pEntry->MaxRAmpduFactor == 0) {
1749		/* If HT AP doesn't support MaxRAmpduFactor = 1, we need to set max PSDU to 0. */
1750		/* Because our Init value is 1 at MACRegTable. */
1751		RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, 0x0fff);
1752	}
1753	/* Patch for Marvel AP to gain high throughput */
1754	/* Need to set as following, */
1755	/* 1. Set txop in register-EDCA_AC0_CFG as 0x60 */
1756	/* 2. Set EnTXWriteBackDDONE in register-WPDMA_GLO_CFG as zero */
1757	/* 3. PBF_MAX_PCNT as 0x1F3FBF9F */
1758	/* 4. kick per two packets when dequeue */
1759	/* */
1760	/* Txop can only be modified when RDG is off, WMM is disable and TxBurst is enable */
1761	/* */
1762	/* if 1. Legacy AP WMM on,  or 2. 11n AP, AMPDU disable.  Force turn off burst no matter what bEnableTxBurst is. */
1763	if (!((pAd->CommonCfg.RxStream == 1) && (pAd->CommonCfg.TxStream == 1))
1764	    && (pAd->StaCfg.bForceTxBurst == FALSE)
1765	    &&
1766	    (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
1767	      && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
1768	     || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE)
1769		 && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE)))) {
1770		RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
1771		Data &= 0xFFFFFF00;
1772		RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
1773
1774		RTMP_IO_WRITE32(pAd, PBF_MAX_PCNT, 0x1F3F7F9F);
1775		DBGPRINT(RT_DEBUG_TRACE, ("Txburst 1\n"));
1776	} else if (pAd->CommonCfg.bEnableTxBurst) {
1777		RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
1778		Data &= 0xFFFFFF00;
1779		Data |= 0x60;
1780		RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
1781		pAd->CommonCfg.IOTestParm.bNowAtherosBurstOn = TRUE;
1782
1783		RTMP_IO_WRITE32(pAd, PBF_MAX_PCNT, 0x1F3FBF9F);
1784		DBGPRINT(RT_DEBUG_TRACE, ("Txburst 2\n"));
1785	} else {
1786		RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
1787		Data &= 0xFFFFFF00;
1788		RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
1789
1790		RTMP_IO_WRITE32(pAd, PBF_MAX_PCNT, 0x1F3F7F9F);
1791		DBGPRINT(RT_DEBUG_TRACE, ("Txburst 3\n"));
1792	}
1793
1794	/* Re-check to turn on TX burst or not. */
1795	if ((pAd->CommonCfg.IOTestParm.bLastAtheros == TRUE)
1796	    && ((STA_WEP_ON(pAd)) || (STA_TKIP_ON(pAd)))) {
1797		pAd->CommonCfg.IOTestParm.bNextDisableRxBA = TRUE;
1798		if (pAd->CommonCfg.bEnableTxBurst) {
1799			u32 MACValue = 0;
1800			/* Force disable  TXOP value in this case. The same action in MLMEUpdateProtect too. */
1801			/* I didn't change PBF_MAX_PCNT setting. */
1802			RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &MACValue);
1803			MACValue &= 0xFFFFFF00;
1804			RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, MACValue);
1805			pAd->CommonCfg.IOTestParm.bNowAtherosBurstOn = FALSE;
1806		}
1807	} else {
1808		pAd->CommonCfg.IOTestParm.bNextDisableRxBA = FALSE;
1809	}
1810
1811	pAd->CommonCfg.IOTestParm.bLastAtheros = FALSE;
1812	COPY_MAC_ADDR(pAd->CommonCfg.LastBssid, pAd->CommonCfg.Bssid);
1813	DBGPRINT(RT_DEBUG_TRACE,
1814		 ("pAd->bNextDisableRxBA= %d \n",
1815		  pAd->CommonCfg.IOTestParm.bNextDisableRxBA));
1816	/* BSSID add in one MAC entry too.  Because in Tx, ASIC need to check Cipher and IV/EIV, BAbitmap */
1817	/* Pther information in MACTab.Content[BSSID_WCID] is not necessary for driver. */
1818	/* Note: As STA, The MACTab.Content[BSSID_WCID]. PairwiseKey and Shared Key for BSS0 are the same. */
1819
1820	if (pAd->StaCfg.WepStatus <= Ndis802_11WEPDisabled) {
1821		if (pAd->StaCfg.WpaSupplicantUP &&
1822		    (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) &&
1823		    (pAd->StaCfg.IEEE8021X == TRUE)) ;
1824		else {
1825			pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
1826			pAd->StaCfg.PrivacyFilter =
1827			    Ndis802_11PrivFilterAcceptAll;
1828		}
1829	}
1830
1831	NdisAcquireSpinLock(&pAd->MacTabLock);
1832	pEntry->PortSecured = pAd->StaCfg.PortSecured;
1833	NdisReleaseSpinLock(&pAd->MacTabLock);
1834
1835	/* */
1836	/* Patch Atheros AP TX will breakdown issue. */
1837	/* AP Model: DLink DWL-8200AP */
1838	/* */
1839	if (INFRA_ON(pAd) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)
1840	    && STA_TKIP_ON(pAd)) {
1841		RTMP_IO_WRITE32(pAd, RX_PARSER_CFG, 0x01);
1842	} else {
1843		RTMP_IO_WRITE32(pAd, RX_PARSER_CFG, 0x00);
1844	}
1845
1846	RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1847
1848	RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW);
1849}
1850
1851/*
1852	==========================================================================
1853
1854	Routine	Description:
1855		Disconnect current BSSID
1856
1857	Arguments:
1858		pAd				- Pointer to our adapter
1859		IsReqFromAP		- Request from AP
1860
1861	Return Value:
1862		None
1863
1864	IRQL = DISPATCH_LEVEL
1865
1866	Note:
1867		We need more information to know it's this requst from AP.
1868		If yes! we need to do extra handling, for example, remove the WPA key.
1869		Otherwise on 4-way handshaking will faied, since the WPA key didn't be
1870		remove while auto reconnect.
1871		Disconnect request from AP, it means we will start afresh 4-way handshaking
1872		on WPA mode.
1873
1874	==========================================================================
1875*/
1876void LinkDown(struct rt_rtmp_adapter *pAd, IN BOOLEAN IsReqFromAP)
1877{
1878	u8 i, ByteValue = 0;
1879
1880	/* Do nothing if monitor mode is on */
1881	if (MONITOR_ON(pAd))
1882		return;
1883
1884	RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW);
1885	/*Comment the codes, beasue the line 2291 call the same function. */
1886	/*RTMPCancelTimer(&pAd->Mlme.PsPollTimer,               &Cancelled); */
1887	/* Not allow go to sleep within linkdown function. */
1888	RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
1889
1890	if (pAd->CommonCfg.bWirelessEvent) {
1891		RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG,
1892				      pAd->MacTab.Content[BSSID_WCID].Addr,
1893				      BSS0, 0);
1894	}
1895
1896	DBGPRINT(RT_DEBUG_TRACE, ("LINK DOWN!\n"));
1897	OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
1898
1899#ifdef RTMP_MAC_PCI
1900	if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) {
1901		BOOLEAN Cancelled;
1902		pAd->Mlme.bPsPollTimerRunning = FALSE;
1903		RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
1904	}
1905
1906	pAd->bPCIclkOff = FALSE;
1907#endif /* RTMP_MAC_PCI // */
1908
1909	if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
1910	    || RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND)
1911	    || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)) {
1912		AUTO_WAKEUP_STRUC AutoWakeupCfg;
1913		AsicForceWakeup(pAd, TRUE);
1914		AutoWakeupCfg.word = 0;
1915		RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
1916		OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
1917	}
1918#ifdef RTMP_MAC_PCI
1919	pAd->bPCIclkOff = FALSE;
1920#endif /* RTMP_MAC_PCI // */
1921
1922	if (ADHOC_ON(pAd))	/* Adhoc mode link down */
1923	{
1924		DBGPRINT(RT_DEBUG_TRACE, ("LINK DOWN 1!\n"));
1925
1926		OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON);
1927		OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
1928		pAd->IndicateMediaState = NdisMediaStateDisconnected;
1929		RTMP_IndicateMediaState(pAd);
1930		pAd->ExtraInfo = GENERAL_LINK_DOWN;
1931		BssTableDeleteEntry(&pAd->ScanTab, pAd->CommonCfg.Bssid,
1932				    pAd->CommonCfg.Channel);
1933		DBGPRINT(RT_DEBUG_TRACE,
1934			 (" MacTab.Size=%d !\n", pAd->MacTab.Size));
1935	} else			/* Infra structure mode */
1936	{
1937		DBGPRINT(RT_DEBUG_TRACE, ("LINK DOWN 2!\n"));
1938
1939		OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON);
1940		OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
1941
1942		/* Saved last SSID for linkup comparison */
1943		pAd->CommonCfg.LastSsidLen = pAd->CommonCfg.SsidLen;
1944		NdisMoveMemory(pAd->CommonCfg.LastSsid, pAd->CommonCfg.Ssid,
1945			       pAd->CommonCfg.LastSsidLen);
1946		COPY_MAC_ADDR(pAd->CommonCfg.LastBssid, pAd->CommonCfg.Bssid);
1947		if (pAd->MlmeAux.CurrReqIsFromNdis == TRUE) {
1948			pAd->IndicateMediaState = NdisMediaStateDisconnected;
1949			RTMP_IndicateMediaState(pAd);
1950			pAd->ExtraInfo = GENERAL_LINK_DOWN;
1951			DBGPRINT(RT_DEBUG_TRACE,
1952				 ("NDIS_STATUS_MEDIA_DISCONNECT Event A!\n"));
1953			pAd->MlmeAux.CurrReqIsFromNdis = FALSE;
1954		} else {
1955			/* */
1956			/* If disassociation request is from NDIS, then we don't need to delete BSSID from entry. */
1957			/* Otherwise lost beacon or receive De-Authentication from AP, */
1958			/* then we should delete BSSID from BssTable. */
1959			/* If we don't delete from entry, roaming will fail. */
1960			/* */
1961			BssTableDeleteEntry(&pAd->ScanTab, pAd->CommonCfg.Bssid,
1962					    pAd->CommonCfg.Channel);
1963		}
1964
1965		/* restore back to - */
1966		/*      1. long slot (20 us) or short slot (9 us) time */
1967		/*      2. turn on/off RTS/CTS and/or CTS-to-self protection */
1968		/*      3. short preamble */
1969		OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED);
1970
1971	}
1972
1973	for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
1974		if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
1975			MacTableDeleteEntry(pAd, pAd->MacTab.Content[i].Aid,
1976					    pAd->MacTab.Content[i].Addr);
1977	}
1978
1979	AsicSetSlotTime(pAd, TRUE);	/*FALSE); */
1980	AsicSetEdcaParm(pAd, NULL);
1981
1982	/* Set LED */
1983	RTMPSetLED(pAd, LED_LINK_DOWN);
1984	pAd->LedIndicatorStrength = 0xF0;
1985	RTMPSetSignalLED(pAd, -100);	/* Force signal strength Led to be turned off, firmware is not done it. */
1986
1987	AsicDisableSync(pAd);
1988
1989	pAd->Mlme.PeriodicRound = 0;
1990	pAd->Mlme.OneSecPeriodicRound = 0;
1991
1992	if (pAd->StaCfg.BssType == BSS_INFRA) {
1993		/* Remove StaCfg Information after link down */
1994		NdisZeroMemory(pAd->CommonCfg.Bssid, MAC_ADDR_LEN);
1995		NdisZeroMemory(pAd->CommonCfg.Ssid, MAX_LEN_OF_SSID);
1996		pAd->CommonCfg.SsidLen = 0;
1997	}
1998
1999	NdisZeroMemory(&pAd->MlmeAux.HtCapability, sizeof(struct rt_ht_capability_ie));
2000	NdisZeroMemory(&pAd->MlmeAux.AddHtInfo, sizeof(struct rt_add_ht_info_ie));
2001	pAd->MlmeAux.HtCapabilityLen = 0;
2002	pAd->MlmeAux.NewExtChannelOffset = 0xff;
2003
2004	/* Reset WPA-PSK state. Only reset when supplicant enabled */
2005	if (pAd->StaCfg.WpaState != SS_NOTUSE) {
2006		pAd->StaCfg.WpaState = SS_START;
2007		/* Clear Replay counter */
2008		NdisZeroMemory(pAd->StaCfg.ReplayCounter, 8);
2009
2010	}
2011	/* */
2012	/* if link down come from AP, we need to remove all WPA keys on WPA mode. */
2013	/* otherwise will cause 4-way handshaking failed, since the WPA key not empty. */
2014	/* */
2015	if ((IsReqFromAP) && (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)) {
2016		/* Remove all WPA keys */
2017		RTMPWPARemoveAllKeys(pAd);
2018	}
2019	/* 802.1x port control */
2020
2021	/* Prevent clear PortSecured here with static WEP */
2022	/* NetworkManger set security policy first then set SSID to connect AP. */
2023	if (pAd->StaCfg.WpaSupplicantUP &&
2024	    (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) &&
2025	    (pAd->StaCfg.IEEE8021X == FALSE)) {
2026		pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
2027	} else {
2028		pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
2029		pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilter8021xWEP;
2030	}
2031
2032	NdisAcquireSpinLock(&pAd->MacTabLock);
2033	NdisZeroMemory(&pAd->MacTab, sizeof(struct rt_mac_table));
2034	pAd->MacTab.Content[BSSID_WCID].PortSecured = pAd->StaCfg.PortSecured;
2035	NdisReleaseSpinLock(&pAd->MacTabLock);
2036
2037	pAd->StaCfg.MicErrCnt = 0;
2038
2039	pAd->IndicateMediaState = NdisMediaStateDisconnected;
2040	/* Update extra information to link is up */
2041	pAd->ExtraInfo = GENERAL_LINK_DOWN;
2042
2043	pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE;
2044
2045#ifdef RTMP_MAC_USB
2046	pAd->bUsbTxBulkAggre = FALSE;
2047#endif /* RTMP_MAC_USB // */
2048
2049	/* Clean association information */
2050	NdisZeroMemory(&pAd->StaCfg.AssocInfo,
2051		       sizeof(struct rt_ndis_802_11_association_information));
2052	pAd->StaCfg.AssocInfo.Length =
2053	    sizeof(struct rt_ndis_802_11_association_information);
2054	pAd->StaCfg.ReqVarIELen = 0;
2055	pAd->StaCfg.ResVarIELen = 0;
2056
2057	/* */
2058	/* Reset RSSI value after link down */
2059	/* */
2060	pAd->StaCfg.RssiSample.AvgRssi0 = 0;
2061	pAd->StaCfg.RssiSample.AvgRssi0X8 = 0;
2062	pAd->StaCfg.RssiSample.AvgRssi1 = 0;
2063	pAd->StaCfg.RssiSample.AvgRssi1X8 = 0;
2064	pAd->StaCfg.RssiSample.AvgRssi2 = 0;
2065	pAd->StaCfg.RssiSample.AvgRssi2X8 = 0;
2066
2067	/* Restore MlmeRate */
2068	pAd->CommonCfg.MlmeRate = pAd->CommonCfg.BasicMlmeRate;
2069	pAd->CommonCfg.RtsRate = pAd->CommonCfg.BasicMlmeRate;
2070
2071	/* */
2072	/* After Link down, reset piggy-back setting in ASIC. Disable RDG. */
2073	/* */
2074	if (pAd->CommonCfg.BBPCurrentBW == BW_40) {
2075		pAd->CommonCfg.BBPCurrentBW = BW_20;
2076		RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &ByteValue);
2077		ByteValue &= (~0x18);
2078		RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, ByteValue);
2079	}
2080	/* Reset DAC */
2081	RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &ByteValue);
2082	ByteValue &= (~0x18);
2083	if (pAd->Antenna.field.TxPath == 2) {
2084		ByteValue |= 0x10;
2085	}
2086	RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, ByteValue);
2087
2088	RTMPSetPiggyBack(pAd, FALSE);
2089	OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_PIGGYBACK_INUSED);
2090
2091	pAd->CommonCfg.BACapability.word = pAd->CommonCfg.REGBACapability.word;
2092
2093	/* Restore all settings in the following. */
2094	AsicUpdateProtect(pAd, 0,
2095			  (ALLN_SETPROTECT | CCKSETPROTECT | OFDMSETPROTECT),
2096			  TRUE, FALSE);
2097	AsicDisableRDG(pAd);
2098	pAd->CommonCfg.IOTestParm.bCurrentAtheros = FALSE;
2099	pAd->CommonCfg.IOTestParm.bNowAtherosBurstOn = FALSE;
2100
2101	RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, 0x1fff);
2102	RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
2103
2104/* Allow go to sleep after linkdown steps. */
2105	RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
2106
2107	RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1, NULL, NULL, 0);
2108
2109#ifdef RT30xx
2110	if ((IS_RT30xx(pAd) || IS_RT3090(pAd) || IS_RT3390(pAd))
2111	    && (pAd->Antenna.field.RxPath > 1 || pAd->Antenna.field.TxPath > 1)) {
2112		RTMP_ASIC_MMPS_DISABLE(pAd);
2113	}
2114#endif /* RT30xx // */
2115}
2116
2117/*
2118	==========================================================================
2119	Description:
2120
2121	IRQL = DISPATCH_LEVEL
2122
2123	==========================================================================
2124*/
2125void IterateOnBssTab(struct rt_rtmp_adapter *pAd)
2126{
2127	struct rt_mlme_start_req StartReq;
2128	struct rt_mlme_join_req JoinReq;
2129	unsigned long BssIdx;
2130
2131	/* Change the wepstatus to original wepstatus */
2132	pAd->StaCfg.WepStatus = pAd->StaCfg.OrigWepStatus;
2133	pAd->StaCfg.PairCipher = pAd->StaCfg.OrigWepStatus;
2134	pAd->StaCfg.GroupCipher = pAd->StaCfg.OrigWepStatus;
2135
2136	BssIdx = pAd->MlmeAux.BssIdx;
2137	if (BssIdx < pAd->MlmeAux.SsidBssTab.BssNr) {
2138		/* Check cipher suite, AP must have more secured cipher than station setting */
2139		/* Set the Pairwise and Group cipher to match the intended AP setting */
2140		/* We can only connect to AP with less secured cipher setting */
2141		if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA)
2142		    || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) {
2143			pAd->StaCfg.GroupCipher =
2144			    pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.
2145			    GroupCipher;
2146
2147			if (pAd->StaCfg.WepStatus ==
2148			    pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.
2149			    PairCipher)
2150				pAd->StaCfg.PairCipher =
2151				    pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].
2152				    WPA.PairCipher;
2153			else if (pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.
2154				 PairCipherAux != Ndis802_11WEPDisabled)
2155				pAd->StaCfg.PairCipher =
2156				    pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].
2157				    WPA.PairCipherAux;
2158			else	/* There is no PairCipher Aux, downgrade our capability to TKIP */
2159				pAd->StaCfg.PairCipher =
2160				    Ndis802_11Encryption2Enabled;
2161		} else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2)
2162			   || (pAd->StaCfg.AuthMode ==
2163			       Ndis802_11AuthModeWPA2PSK)) {
2164			pAd->StaCfg.GroupCipher =
2165			    pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.
2166			    GroupCipher;
2167
2168			if (pAd->StaCfg.WepStatus ==
2169			    pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.
2170			    PairCipher)
2171				pAd->StaCfg.PairCipher =
2172				    pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].
2173				    WPA2.PairCipher;
2174			else if (pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.
2175				 PairCipherAux != Ndis802_11WEPDisabled)
2176				pAd->StaCfg.PairCipher =
2177				    pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].
2178				    WPA2.PairCipherAux;
2179			else	/* There is no PairCipher Aux, downgrade our capability to TKIP */
2180				pAd->StaCfg.PairCipher =
2181				    Ndis802_11Encryption2Enabled;
2182
2183			/* RSN capability */
2184			pAd->StaCfg.RsnCapability =
2185			    pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.
2186			    RsnCapability;
2187		}
2188		/* Set Mix cipher flag */
2189		pAd->StaCfg.bMixCipher =
2190		    (pAd->StaCfg.PairCipher ==
2191		     pAd->StaCfg.GroupCipher) ? FALSE : TRUE;
2192		/*if (pAd->StaCfg.bMixCipher == TRUE)
2193		   {
2194		   // If mix cipher, re-build RSNIE
2195		   RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, 0);
2196		   } */
2197
2198		DBGPRINT(RT_DEBUG_TRACE,
2199			 ("CNTL - iterate BSS %ld of %d\n", BssIdx,
2200			  pAd->MlmeAux.SsidBssTab.BssNr));
2201		JoinParmFill(pAd, &JoinReq, BssIdx);
2202		MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_JOIN_REQ,
2203			    sizeof(struct rt_mlme_join_req), &JoinReq);
2204		pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_JOIN;
2205	} else if (pAd->StaCfg.BssType == BSS_ADHOC) {
2206		DBGPRINT(RT_DEBUG_TRACE,
2207			 ("CNTL - All BSS fail; start a new ADHOC (Ssid=%s)...\n",
2208			  pAd->MlmeAux.Ssid));
2209		StartParmFill(pAd, &StartReq, (char *)pAd->MlmeAux.Ssid,
2210			      pAd->MlmeAux.SsidLen);
2211		MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ,
2212			    sizeof(struct rt_mlme_start_req), &StartReq);
2213		pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
2214	} else			/* no more BSS */
2215	{
2216
2217		{
2218			AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
2219			AsicLockChannel(pAd, pAd->CommonCfg.Channel);
2220			DBGPRINT(RT_DEBUG_TRACE,
2221				 ("CNTL - All roaming failed, restore to channel %d, Total BSS[%02d]\n",
2222				  pAd->CommonCfg.Channel, pAd->ScanTab.BssNr));
2223		}
2224
2225		pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
2226	}
2227}
2228
2229/* for re-association only */
2230/* IRQL = DISPATCH_LEVEL */
2231void IterateOnBssTab2(struct rt_rtmp_adapter *pAd)
2232{
2233	struct rt_mlme_assoc_req ReassocReq;
2234	unsigned long BssIdx;
2235	struct rt_bss_entry *pBss;
2236
2237	BssIdx = pAd->MlmeAux.RoamIdx;
2238	pBss = &pAd->MlmeAux.RoamTab.BssEntry[BssIdx];
2239
2240	if (BssIdx < pAd->MlmeAux.RoamTab.BssNr) {
2241		DBGPRINT(RT_DEBUG_TRACE,
2242			 ("CNTL - iterate BSS %ld of %d\n", BssIdx,
2243			  pAd->MlmeAux.RoamTab.BssNr));
2244
2245		AsicSwitchChannel(pAd, pBss->Channel, FALSE);
2246		AsicLockChannel(pAd, pBss->Channel);
2247
2248		/* reassociate message has the same structure as associate message */
2249		AssocParmFill(pAd, &ReassocReq, pBss->Bssid,
2250			      pBss->CapabilityInfo, ASSOC_TIMEOUT,
2251			      pAd->StaCfg.DefaultListenCount);
2252		MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_REASSOC_REQ,
2253			    sizeof(struct rt_mlme_assoc_req), &ReassocReq);
2254
2255		pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_REASSOC;
2256	} else			/* no more BSS */
2257	{
2258
2259		{
2260			AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
2261			AsicLockChannel(pAd, pAd->CommonCfg.Channel);
2262			DBGPRINT(RT_DEBUG_TRACE,
2263				 ("CNTL - All roaming failed, restore to channel %d, Total BSS[%02d]\n",
2264				  pAd->CommonCfg.Channel, pAd->ScanTab.BssNr));
2265		}
2266
2267		pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
2268	}
2269}
2270
2271/*
2272	==========================================================================
2273	Description:
2274
2275	IRQL = DISPATCH_LEVEL
2276
2277	==========================================================================
2278*/
2279void JoinParmFill(struct rt_rtmp_adapter *pAd,
2280		  struct rt_mlme_join_req *JoinReq, unsigned long BssIdx)
2281{
2282	JoinReq->BssIdx = BssIdx;
2283}
2284
2285/*
2286	==========================================================================
2287	Description:
2288
2289	IRQL = DISPATCH_LEVEL
2290
2291	==========================================================================
2292*/
2293void ScanParmFill(struct rt_rtmp_adapter *pAd,
2294		  struct rt_mlme_scan_req *ScanReq,
2295		  char Ssid[],
2296		  u8 SsidLen, u8 BssType, u8 ScanType)
2297{
2298	NdisZeroMemory(ScanReq->Ssid, MAX_LEN_OF_SSID);
2299	ScanReq->SsidLen = SsidLen;
2300	NdisMoveMemory(ScanReq->Ssid, Ssid, SsidLen);
2301	ScanReq->BssType = BssType;
2302	ScanReq->ScanType = ScanType;
2303}
2304
2305/*
2306	==========================================================================
2307	Description:
2308
2309	IRQL = DISPATCH_LEVEL
2310
2311	==========================================================================
2312*/
2313void StartParmFill(struct rt_rtmp_adapter *pAd,
2314		   struct rt_mlme_start_req *StartReq,
2315		   char Ssid[], u8 SsidLen)
2316{
2317	ASSERT(SsidLen <= MAX_LEN_OF_SSID);
2318	NdisMoveMemory(StartReq->Ssid, Ssid, SsidLen);
2319	StartReq->SsidLen = SsidLen;
2320}
2321
2322/*
2323	==========================================================================
2324	Description:
2325
2326	IRQL = DISPATCH_LEVEL
2327
2328	==========================================================================
2329*/
2330void AuthParmFill(struct rt_rtmp_adapter *pAd,
2331		  struct rt_mlme_auth_req *AuthReq,
2332		  u8 *pAddr, u16 Alg)
2333{
2334	COPY_MAC_ADDR(AuthReq->Addr, pAddr);
2335	AuthReq->Alg = Alg;
2336	AuthReq->Timeout = AUTH_TIMEOUT;
2337}
2338
2339/*
2340	==========================================================================
2341	Description:
2342
2343	IRQL = DISPATCH_LEVEL
2344
2345	==========================================================================
2346 */
2347#ifdef RTMP_MAC_PCI
2348void ComposePsPoll(struct rt_rtmp_adapter *pAd)
2349{
2350	NdisZeroMemory(&pAd->PsPollFrame, sizeof(struct rt_pspoll_frame));
2351	pAd->PsPollFrame.FC.Type = BTYPE_CNTL;
2352	pAd->PsPollFrame.FC.SubType = SUBTYPE_PS_POLL;
2353	pAd->PsPollFrame.Aid = pAd->StaActive.Aid | 0xC000;
2354	COPY_MAC_ADDR(pAd->PsPollFrame.Bssid, pAd->CommonCfg.Bssid);
2355	COPY_MAC_ADDR(pAd->PsPollFrame.Ta, pAd->CurrentAddress);
2356}
2357
2358/* IRQL = DISPATCH_LEVEL */
2359void ComposeNullFrame(struct rt_rtmp_adapter *pAd)
2360{
2361	NdisZeroMemory(&pAd->NullFrame, sizeof(struct rt_header_802_11));
2362	pAd->NullFrame.FC.Type = BTYPE_DATA;
2363	pAd->NullFrame.FC.SubType = SUBTYPE_NULL_FUNC;
2364	pAd->NullFrame.FC.ToDs = 1;
2365	COPY_MAC_ADDR(pAd->NullFrame.Addr1, pAd->CommonCfg.Bssid);
2366	COPY_MAC_ADDR(pAd->NullFrame.Addr2, pAd->CurrentAddress);
2367	COPY_MAC_ADDR(pAd->NullFrame.Addr3, pAd->CommonCfg.Bssid);
2368}
2369#endif /* RTMP_MAC_PCI // */
2370#ifdef RTMP_MAC_USB
2371void MlmeCntlConfirm(struct rt_rtmp_adapter *pAd, unsigned long MsgType, u16 Msg)
2372{
2373	MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MsgType, sizeof(u16),
2374		    &Msg);
2375}
2376
2377void ComposePsPoll(struct rt_rtmp_adapter *pAd)
2378{
2379	struct rt_txinfo *pTxInfo;
2380	struct rt_txwi * pTxWI;
2381
2382	DBGPRINT(RT_DEBUG_TRACE, ("ComposePsPoll\n"));
2383	NdisZeroMemory(&pAd->PsPollFrame, sizeof(struct rt_pspoll_frame));
2384
2385	pAd->PsPollFrame.FC.PwrMgmt = 0;
2386	pAd->PsPollFrame.FC.Type = BTYPE_CNTL;
2387	pAd->PsPollFrame.FC.SubType = SUBTYPE_PS_POLL;
2388	pAd->PsPollFrame.Aid = pAd->StaActive.Aid | 0xC000;
2389	COPY_MAC_ADDR(pAd->PsPollFrame.Bssid, pAd->CommonCfg.Bssid);
2390	COPY_MAC_ADDR(pAd->PsPollFrame.Ta, pAd->CurrentAddress);
2391
2392	RTMPZeroMemory(&pAd->PsPollContext.TransferBuffer->field.
2393		       WirelessPacket[0], 100);
2394	pTxInfo =
2395	    (struct rt_txinfo *)& pAd->PsPollContext.TransferBuffer->field.
2396	    WirelessPacket[0];
2397	RTMPWriteTxInfo(pAd, pTxInfo,
2398			(u16)(sizeof(struct rt_pspoll_frame) + TXWI_SIZE), TRUE,
2399			EpToQueue[MGMTPIPEIDX], FALSE, FALSE);
2400	pTxWI =
2401	    (struct rt_txwi *) & pAd->PsPollContext.TransferBuffer->field.
2402	    WirelessPacket[TXINFO_SIZE];
2403	RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, 0,
2404		      BSSID_WCID, (sizeof(struct rt_pspoll_frame)), 0, 0,
2405		      (u8)pAd->CommonCfg.MlmeTransmit.field.MCS,
2406		      IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
2407	RTMPMoveMemory(&pAd->PsPollContext.TransferBuffer->field.
2408		       WirelessPacket[TXWI_SIZE + TXINFO_SIZE],
2409		       &pAd->PsPollFrame, sizeof(struct rt_pspoll_frame));
2410	/* Append 4 extra zero bytes. */
2411	pAd->PsPollContext.BulkOutSize =
2412	    TXINFO_SIZE + TXWI_SIZE + sizeof(struct rt_pspoll_frame) + 4;
2413}
2414
2415/* IRQL = DISPATCH_LEVEL */
2416void ComposeNullFrame(struct rt_rtmp_adapter *pAd)
2417{
2418	struct rt_txinfo *pTxInfo;
2419	struct rt_txwi * pTxWI;
2420
2421	NdisZeroMemory(&pAd->NullFrame, sizeof(struct rt_header_802_11));
2422	pAd->NullFrame.FC.Type = BTYPE_DATA;
2423	pAd->NullFrame.FC.SubType = SUBTYPE_NULL_FUNC;
2424	pAd->NullFrame.FC.ToDs = 1;
2425	COPY_MAC_ADDR(pAd->NullFrame.Addr1, pAd->CommonCfg.Bssid);
2426	COPY_MAC_ADDR(pAd->NullFrame.Addr2, pAd->CurrentAddress);
2427	COPY_MAC_ADDR(pAd->NullFrame.Addr3, pAd->CommonCfg.Bssid);
2428	RTMPZeroMemory(&pAd->NullContext.TransferBuffer->field.
2429		       WirelessPacket[0], 100);
2430	pTxInfo =
2431	    (struct rt_txinfo *)& pAd->NullContext.TransferBuffer->field.
2432	    WirelessPacket[0];
2433	RTMPWriteTxInfo(pAd, pTxInfo,
2434			(u16)(sizeof(struct rt_header_802_11) + TXWI_SIZE), TRUE,
2435			EpToQueue[MGMTPIPEIDX], FALSE, FALSE);
2436	pTxWI =
2437	    (struct rt_txwi *) & pAd->NullContext.TransferBuffer->field.
2438	    WirelessPacket[TXINFO_SIZE];
2439	RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, 0,
2440		      BSSID_WCID, (sizeof(struct rt_header_802_11)), 0, 0,
2441		      (u8)pAd->CommonCfg.MlmeTransmit.field.MCS,
2442		      IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
2443	RTMPMoveMemory(&pAd->NullContext.TransferBuffer->field.
2444		       WirelessPacket[TXWI_SIZE + TXINFO_SIZE], &pAd->NullFrame,
2445		       sizeof(struct rt_header_802_11));
2446	pAd->NullContext.BulkOutSize =
2447	    TXINFO_SIZE + TXWI_SIZE + sizeof(pAd->NullFrame) + 4;
2448}
2449#endif /* RTMP_MAC_USB // */
2450
2451/*
2452	==========================================================================
2453	Description:
2454		Pre-build a BEACON frame in the shared memory
2455
2456	IRQL = PASSIVE_LEVEL
2457	IRQL = DISPATCH_LEVEL
2458
2459	==========================================================================
2460*/
2461unsigned long MakeIbssBeacon(struct rt_rtmp_adapter *pAd)
2462{
2463	u8 DsLen = 1, IbssLen = 2;
2464	u8 LocalErpIe[3] = { IE_ERP, 1, 0x04 };
2465	struct rt_header_802_11 BcnHdr;
2466	u16 CapabilityInfo;
2467	LARGE_INTEGER FakeTimestamp;
2468	unsigned long FrameLen = 0;
2469	struct rt_txwi * pTxWI = &pAd->BeaconTxWI;
2470	u8 *pBeaconFrame = pAd->BeaconBuf;
2471	BOOLEAN Privacy;
2472	u8 SupRate[MAX_LEN_OF_SUPPORTED_RATES];
2473	u8 SupRateLen = 0;
2474	u8 ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
2475	u8 ExtRateLen = 0;
2476	u8 RSNIe = IE_WPA;
2477
2478	if ((pAd->CommonCfg.PhyMode == PHY_11B)
2479	    && (pAd->CommonCfg.Channel <= 14)) {
2480		SupRate[0] = 0x82;	/* 1 mbps */
2481		SupRate[1] = 0x84;	/* 2 mbps */
2482		SupRate[2] = 0x8b;	/* 5.5 mbps */
2483		SupRate[3] = 0x96;	/* 11 mbps */
2484		SupRateLen = 4;
2485		ExtRateLen = 0;
2486	} else if (pAd->CommonCfg.Channel > 14) {
2487		SupRate[0] = 0x8C;	/* 6 mbps, in units of 0.5 Mbps, basic rate */
2488		SupRate[1] = 0x12;	/* 9 mbps, in units of 0.5 Mbps */
2489		SupRate[2] = 0x98;	/* 12 mbps, in units of 0.5 Mbps, basic rate */
2490		SupRate[3] = 0x24;	/* 18 mbps, in units of 0.5 Mbps */
2491		SupRate[4] = 0xb0;	/* 24 mbps, in units of 0.5 Mbps, basic rate */
2492		SupRate[5] = 0x48;	/* 36 mbps, in units of 0.5 Mbps */
2493		SupRate[6] = 0x60;	/* 48 mbps, in units of 0.5 Mbps */
2494		SupRate[7] = 0x6c;	/* 54 mbps, in units of 0.5 Mbps */
2495		SupRateLen = 8;
2496		ExtRateLen = 0;
2497
2498		/* */
2499		/* Also Update MlmeRate & RtsRate for G only & A only */
2500		/* */
2501		pAd->CommonCfg.MlmeRate = RATE_6;
2502		pAd->CommonCfg.RtsRate = RATE_6;
2503		pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
2504		pAd->CommonCfg.MlmeTransmit.field.MCS =
2505		    OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
2506		pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE =
2507		    MODE_OFDM;
2508		pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS =
2509		    OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
2510	} else {
2511		SupRate[0] = 0x82;	/* 1 mbps */
2512		SupRate[1] = 0x84;	/* 2 mbps */
2513		SupRate[2] = 0x8b;	/* 5.5 mbps */
2514		SupRate[3] = 0x96;	/* 11 mbps */
2515		SupRateLen = 4;
2516
2517		ExtRate[0] = 0x0C;	/* 6 mbps, in units of 0.5 Mbps, */
2518		ExtRate[1] = 0x12;	/* 9 mbps, in units of 0.5 Mbps */
2519		ExtRate[2] = 0x18;	/* 12 mbps, in units of 0.5 Mbps, */
2520		ExtRate[3] = 0x24;	/* 18 mbps, in units of 0.5 Mbps */
2521		ExtRate[4] = 0x30;	/* 24 mbps, in units of 0.5 Mbps, */
2522		ExtRate[5] = 0x48;	/* 36 mbps, in units of 0.5 Mbps */
2523		ExtRate[6] = 0x60;	/* 48 mbps, in units of 0.5 Mbps */
2524		ExtRate[7] = 0x6c;	/* 54 mbps, in units of 0.5 Mbps */
2525		ExtRateLen = 8;
2526	}
2527
2528	pAd->StaActive.SupRateLen = SupRateLen;
2529	NdisMoveMemory(pAd->StaActive.SupRate, SupRate, SupRateLen);
2530	pAd->StaActive.ExtRateLen = ExtRateLen;
2531	NdisMoveMemory(pAd->StaActive.ExtRate, ExtRate, ExtRateLen);
2532
2533	/* compose IBSS beacon frame */
2534	MgtMacHeaderInit(pAd, &BcnHdr, SUBTYPE_BEACON, 0, BROADCAST_ADDR,
2535			 pAd->CommonCfg.Bssid);
2536	Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled)
2537	    || (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled)
2538	    || (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled);
2539	CapabilityInfo =
2540	    CAP_GENERATE(0, 1, Privacy,
2541			 (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort),
2542			 0, 0);
2543
2544	MakeOutgoingFrame(pBeaconFrame, &FrameLen,
2545			  sizeof(struct rt_header_802_11), &BcnHdr,
2546			  TIMESTAMP_LEN, &FakeTimestamp,
2547			  2, &pAd->CommonCfg.BeaconPeriod,
2548			  2, &CapabilityInfo,
2549			  1, &SsidIe,
2550			  1, &pAd->CommonCfg.SsidLen,
2551			  pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid,
2552			  1, &SupRateIe,
2553			  1, &SupRateLen,
2554			  SupRateLen, SupRate,
2555			  1, &DsIe,
2556			  1, &DsLen,
2557			  1, &pAd->CommonCfg.Channel,
2558			  1, &IbssIe,
2559			  1, &IbssLen, 2, &pAd->StaActive.AtimWin, END_OF_ARGS);
2560
2561	/* add ERP_IE and EXT_RAE IE of in 802.11g */
2562	if (ExtRateLen) {
2563		unsigned long tmp;
2564
2565		MakeOutgoingFrame(pBeaconFrame + FrameLen, &tmp,
2566				  3, LocalErpIe,
2567				  1, &ExtRateIe,
2568				  1, &ExtRateLen,
2569				  ExtRateLen, ExtRate, END_OF_ARGS);
2570		FrameLen += tmp;
2571	}
2572	/* If adhoc secruity is set for WPA-None, append the cipher suite IE */
2573	if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) {
2574		unsigned long tmp;
2575		RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus,
2576			      BSS0);
2577
2578		MakeOutgoingFrame(pBeaconFrame + FrameLen, &tmp,
2579				  1, &RSNIe,
2580				  1, &pAd->StaCfg.RSNIE_Len,
2581				  pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE,
2582				  END_OF_ARGS);
2583		FrameLen += tmp;
2584	}
2585
2586	if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) {
2587		unsigned long TmpLen;
2588		u8 HtLen, HtLen1;
2589
2590		/* add HT Capability IE */
2591		HtLen = sizeof(pAd->CommonCfg.HtCapability);
2592		HtLen1 = sizeof(pAd->CommonCfg.AddHTInfo);
2593
2594		MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen,
2595				  1, &HtCapIe,
2596				  1, &HtLen,
2597				  HtLen, &pAd->CommonCfg.HtCapability,
2598				  1, &AddHtInfoIe,
2599				  1, &HtLen1,
2600				  HtLen1, &pAd->CommonCfg.AddHTInfo,
2601				  END_OF_ARGS);
2602
2603		FrameLen += TmpLen;
2604	}
2605	/*beacon use reserved WCID 0xff */
2606	if (pAd->CommonCfg.Channel > 14) {
2607		RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, TRUE, FALSE, FALSE,
2608			      TRUE, 0, 0xff, FrameLen, PID_MGMT, PID_BEACON,
2609			      RATE_1, IFS_HTTXOP, FALSE,
2610			      &pAd->CommonCfg.MlmeTransmit);
2611	} else {
2612		/* Set to use 1Mbps for Adhoc beacon. */
2613		HTTRANSMIT_SETTING Transmit;
2614		Transmit.word = 0;
2615		RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, TRUE, FALSE, FALSE,
2616			      TRUE, 0, 0xff, FrameLen, PID_MGMT, PID_BEACON,
2617			      RATE_1, IFS_HTTXOP, FALSE, &Transmit);
2618	}
2619
2620	DBGPRINT(RT_DEBUG_TRACE,
2621		 ("MakeIbssBeacon (len=%ld), SupRateLen=%d, ExtRateLen=%d, Channel=%d, PhyMode=%d\n",
2622		  FrameLen, SupRateLen, ExtRateLen, pAd->CommonCfg.Channel,
2623		  pAd->CommonCfg.PhyMode));
2624	return FrameLen;
2625}
2626