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