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