Staging: rt2860: remove dead code
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / rt2860 / sta / sync.c
blob17dbe1dc2196edc8fff20cfa212ae2894cb21688
1 /*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
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 *************************************************************************
27 Module Name:
28 sync.c
30 Abstract:
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
38 #include "../rt_config.h"
40 #define AC0_DEF_TXOP 0
41 #define AC1_DEF_TXOP 0
42 #define AC2_DEF_TXOP 94
43 #define AC3_DEF_TXOP 47
45 VOID AdhocTurnOnQos(
46 IN PRTMP_ADAPTER pAd)
48 // Turn on QOs if use HT rate.
49 if (pAd->CommonCfg.APEdcaParm.bValid == FALSE)
51 pAd->CommonCfg.APEdcaParm.bValid = TRUE;
52 pAd->CommonCfg.APEdcaParm.Aifsn[0] = 3;
53 pAd->CommonCfg.APEdcaParm.Aifsn[1] = 7;
54 pAd->CommonCfg.APEdcaParm.Aifsn[2] = 1;
55 pAd->CommonCfg.APEdcaParm.Aifsn[3] = 1;
57 pAd->CommonCfg.APEdcaParm.Cwmin[0] = 4;
58 pAd->CommonCfg.APEdcaParm.Cwmin[1] = 4;
59 pAd->CommonCfg.APEdcaParm.Cwmin[2] = 3;
60 pAd->CommonCfg.APEdcaParm.Cwmin[3] = 2;
62 pAd->CommonCfg.APEdcaParm.Cwmax[0] = 10;
63 pAd->CommonCfg.APEdcaParm.Cwmax[1] = 6;
64 pAd->CommonCfg.APEdcaParm.Cwmax[2] = 4;
65 pAd->CommonCfg.APEdcaParm.Cwmax[3] = 3;
67 pAd->CommonCfg.APEdcaParm.Txop[0] = 0;
68 pAd->CommonCfg.APEdcaParm.Txop[1] = 0;
69 pAd->CommonCfg.APEdcaParm.Txop[2] = AC2_DEF_TXOP;
70 pAd->CommonCfg.APEdcaParm.Txop[3] = AC3_DEF_TXOP;
72 AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm);
76 ==========================================================================
77 Description:
78 The sync state machine,
79 Parameters:
80 Sm - pointer to the state machine
81 Note:
82 the state machine looks like the following
84 ==========================================================================
86 VOID SyncStateMachineInit(
87 IN PRTMP_ADAPTER pAd,
88 IN STATE_MACHINE *Sm,
89 OUT STATE_MACHINE_FUNC Trans[])
91 StateMachineInit(Sm, Trans, MAX_SYNC_STATE, MAX_SYNC_MSG, (STATE_MACHINE_FUNC)Drop, SYNC_IDLE, SYNC_MACHINE_BASE);
93 // column 1
94 StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)MlmeScanReqAction);
95 StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)MlmeJoinReqAction);
96 StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)MlmeStartReqAction);
97 StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeacon);
98 StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_PROBE_REQ, (STATE_MACHINE_FUNC)PeerProbeReqAction);
100 //column 2
101 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenScan);
102 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenJoin);
103 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenStart);
104 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeaconAtJoinAction);
105 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_BEACON_TIMEOUT, (STATE_MACHINE_FUNC)BeaconTimeoutAtJoinAction);
107 // column 3
108 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenScan);
109 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenJoin);
110 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenStart);
111 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction);
112 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_PROBE_RSP, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction);
113 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_SCAN_TIMEOUT, (STATE_MACHINE_FUNC)ScanTimeoutAction);
115 // timer init
116 RTMPInitTimer(pAd, &pAd->MlmeAux.BeaconTimer, GET_TIMER_FUNCTION(BeaconTimeout), pAd, FALSE);
117 RTMPInitTimer(pAd, &pAd->MlmeAux.ScanTimer, GET_TIMER_FUNCTION(ScanTimeout), pAd, FALSE);
121 ==========================================================================
122 Description:
123 Beacon timeout handler, executed in timer thread
125 IRQL = DISPATCH_LEVEL
127 ==========================================================================
129 VOID BeaconTimeout(
130 IN PVOID SystemSpecific1,
131 IN PVOID FunctionContext,
132 IN PVOID SystemSpecific2,
133 IN PVOID SystemSpecific3)
135 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
137 DBGPRINT(RT_DEBUG_TRACE,("SYNC - BeaconTimeout\n"));
139 // Do nothing if the driver is starting halt state.
140 // This might happen when timer already been fired before cancel timer with mlmehalt
141 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
142 return;
144 if ((pAd->CommonCfg.BBPCurrentBW == BW_40)
147 UCHAR BBPValue = 0;
148 AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
149 AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
150 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
151 BBPValue &= (~0x18);
152 BBPValue |= 0x10;
153 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
154 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n",pAd->CommonCfg.CentralChannel, pAd->ScanTab.BssNr));
157 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_BEACON_TIMEOUT, 0, NULL);
158 RT28XX_MLME_HANDLER(pAd);
162 ==========================================================================
163 Description:
164 Scan timeout handler, executed in timer thread
166 IRQL = DISPATCH_LEVEL
168 ==========================================================================
170 VOID ScanTimeout(
171 IN PVOID SystemSpecific1,
172 IN PVOID FunctionContext,
173 IN PVOID SystemSpecific2,
174 IN PVOID SystemSpecific3)
176 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
179 // Do nothing if the driver is starting halt state.
180 // This might happen when timer already been fired before cancel timer with mlmehalt
181 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
182 return;
184 if (MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_SCAN_TIMEOUT, 0, NULL))
186 RT28XX_MLME_HANDLER(pAd);
188 else
190 // To prevent SyncMachine.CurrState is SCAN_LISTEN forever.
191 pAd->MlmeAux.Channel = 0;
192 ScanNextChannel(pAd);
193 if (pAd->CommonCfg.bWirelessEvent)
195 RTMPSendWirelessEvent(pAd, IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
201 ==========================================================================
202 Description:
203 MLME SCAN req state machine procedure
204 ==========================================================================
206 VOID MlmeScanReqAction(
207 IN PRTMP_ADAPTER pAd,
208 IN MLME_QUEUE_ELEM *Elem)
210 UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, ScanType, BssType, BBPValue = 0;
211 BOOLEAN TimerCancelled;
212 ULONG Now;
213 USHORT Status;
214 PHEADER_802_11 pHdr80211;
215 PUCHAR pOutBuffer = NULL;
216 NDIS_STATUS NStatus;
218 // Check the total scan tries for one single OID command
219 // If this is the CCX 2.0 Case, skip that!
220 if ( !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
222 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeScanReqAction before Startup\n"));
223 return;
226 // Increase the scan retry counters.
227 pAd->StaCfg.ScanCnt++;
229 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) &&
230 (IDLE_ON(pAd)) &&
231 (pAd->StaCfg.bRadio == TRUE) &&
232 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
234 RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE);
237 // first check the parameter sanity
238 if (MlmeScanReqSanity(pAd,
239 Elem->Msg,
240 Elem->MsgLen,
241 &BssType,
242 Ssid,
243 &SsidLen,
244 &ScanType))
247 // Check for channel load and noise hist request
248 // Suspend MSDU only at scan request, not the last two mentioned
249 if ((ScanType == SCAN_CISCO_NOISE) || (ScanType == SCAN_CISCO_CHANNEL_LOAD))
251 if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel)
252 RTMPSuspendMsduTransmission(pAd); // Suspend MSDU transmission here
254 else
256 // Suspend MSDU transmission here
257 RTMPSuspendMsduTransmission(pAd);
261 // To prevent data lost.
262 // Send an NULL data with turned PSM bit on to current associated AP before SCAN progress.
263 // And should send an NULL data with turned PSM bit off to AP, when scan progress done
265 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd)))
267 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer);
268 if (NStatus == NDIS_STATUS_SUCCESS)
270 pHdr80211 = (PHEADER_802_11) pOutBuffer;
271 MgtMacHeaderInit(pAd, pHdr80211, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid);
272 pHdr80211->Duration = 0;
273 pHdr80211->FC.Type = BTYPE_DATA;
274 pHdr80211->FC.PwrMgmt = PWR_SAVE;
276 // Send using priority queue
277 MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11));
278 DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqAction -- Send PSM Data frame for off channel RM\n"));
279 MlmeFreeMemory(pAd, pOutBuffer);
280 RTMPusecDelay(5000);
284 NdisGetSystemUpTime(&Now);
285 pAd->StaCfg.LastScanTime = Now;
286 // reset all the timers
287 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
288 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled);
290 // record desired BSS parameters
291 pAd->MlmeAux.BssType = BssType;
292 pAd->MlmeAux.ScanType = ScanType;
293 pAd->MlmeAux.SsidLen = SsidLen;
294 NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID);
295 NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen);
297 // start from the first channel
298 pAd->MlmeAux.Channel = FirstChannel(pAd);
300 // Change the scan channel when dealing with CCX beacon report
301 if ((ScanType == SCAN_CISCO_PASSIVE) || (ScanType == SCAN_CISCO_ACTIVE) ||
302 (ScanType == SCAN_CISCO_CHANNEL_LOAD) || (ScanType == SCAN_CISCO_NOISE))
303 pAd->MlmeAux.Channel = pAd->StaCfg.CCXScanChannel;
305 // Let BBP register at 20MHz to do scan
306 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
307 BBPValue &= (~0x18);
308 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
309 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n"));
310 ScanNextChannel(pAd);
312 else
314 DBGPRINT_ERR(("SYNC - MlmeScanReqAction() sanity check fail\n"));
315 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
316 Status = MLME_INVALID_FORMAT;
317 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status);
322 ==========================================================================
323 Description:
324 MLME JOIN req state machine procedure
325 ==========================================================================
327 VOID MlmeJoinReqAction(
328 IN PRTMP_ADAPTER pAd,
329 IN MLME_QUEUE_ELEM *Elem)
331 UCHAR BBPValue = 0;
332 BSS_ENTRY *pBss;
333 BOOLEAN TimerCancelled;
334 HEADER_802_11 Hdr80211;
335 NDIS_STATUS NStatus;
336 ULONG FrameLen = 0;
337 PUCHAR pOutBuffer = NULL;
338 PUCHAR pSupRate = NULL;
339 UCHAR SupRateLen;
340 PUCHAR pExtRate = NULL;
341 UCHAR ExtRateLen;
342 UCHAR ASupRate[] = {0x8C, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6C};
343 UCHAR ASupRateLen = sizeof(ASupRate)/sizeof(UCHAR);
344 MLME_JOIN_REQ_STRUCT *pInfo = (MLME_JOIN_REQ_STRUCT *)(Elem->Msg);
346 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeJoinReqAction(BSS #%ld)\n", pInfo->BssIdx));
348 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) &&
349 (IDLE_ON(pAd)) &&
350 (pAd->StaCfg.bRadio == TRUE) &&
351 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
353 RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE);
356 // reset all the timers
357 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled);
358 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
360 pBss = &pAd->MlmeAux.SsidBssTab.BssEntry[pInfo->BssIdx];
362 // record the desired SSID & BSSID we're waiting for
363 COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pBss->Bssid);
365 // If AP's SSID is not hidden, it is OK for updating ssid to MlmeAux again.
366 if (pBss->Hidden == 0)
368 NdisMoveMemory(pAd->MlmeAux.Ssid, pBss->Ssid, pBss->SsidLen);
369 pAd->MlmeAux.SsidLen = pBss->SsidLen;
372 pAd->MlmeAux.BssType = pBss->BssType;
373 pAd->MlmeAux.Channel = pBss->Channel;
374 pAd->MlmeAux.CentralChannel = pBss->CentralChannel;
376 // Let BBP register at 20MHz to do scan
377 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
378 BBPValue &= (~0x18);
379 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
380 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n"));
382 // switch channel and waiting for beacon timer
383 AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE);
384 AsicLockChannel(pAd, pAd->MlmeAux.Channel);
385 RTMPSetTimer(&pAd->MlmeAux.BeaconTimer, JOIN_TIMEOUT);
389 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
390 (pAd->MlmeAux.Channel > 14) &&
391 RadarChannelCheck(pAd, pAd->MlmeAux.Channel))
395 // We can't send any Probe request frame to meet 802.11h.
397 if (pBss->Hidden == 0)
398 break;
402 // send probe request
404 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
405 if (NStatus == NDIS_STATUS_SUCCESS)
407 if (pAd->MlmeAux.Channel <= 14)
409 pSupRate = pAd->CommonCfg.SupRate;
410 SupRateLen = pAd->CommonCfg.SupRateLen;
411 pExtRate = pAd->CommonCfg.ExtRate;
412 ExtRateLen = pAd->CommonCfg.ExtRateLen;
414 else
417 // Overwrite Support Rate, CCK rate are not allowed
419 pSupRate = ASupRate;
420 SupRateLen = ASupRateLen;
421 ExtRateLen = 0;
424 if (pAd->MlmeAux.BssType == BSS_INFRA)
425 MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, pAd->MlmeAux.Bssid, pAd->MlmeAux.Bssid);
426 else
427 MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR);
429 MakeOutgoingFrame(pOutBuffer, &FrameLen,
430 sizeof(HEADER_802_11), &Hdr80211,
431 1, &SsidIe,
432 1, &pAd->MlmeAux.SsidLen,
433 pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid,
434 1, &SupRateIe,
435 1, &SupRateLen,
436 SupRateLen, pSupRate,
437 END_OF_ARGS);
439 if (ExtRateLen)
441 ULONG Tmp;
442 MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp,
443 1, &ExtRateIe,
444 1, &ExtRateLen,
445 ExtRateLen, pExtRate,
446 END_OF_ARGS);
447 FrameLen += Tmp;
451 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
452 MlmeFreeMemory(pAd, pOutBuffer);
454 } while (FALSE);
456 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - Switch to ch %d, Wait BEACON from %02x:%02x:%02x:%02x:%02x:%02x\n",
457 pBss->Channel, pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2], pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5]));
459 pAd->Mlme.SyncMachine.CurrState = JOIN_WAIT_BEACON;
463 ==========================================================================
464 Description:
465 MLME START Request state machine procedure, starting an IBSS
466 ==========================================================================
468 VOID MlmeStartReqAction(
469 IN PRTMP_ADAPTER pAd,
470 IN MLME_QUEUE_ELEM *Elem)
472 UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen;
473 BOOLEAN TimerCancelled;
475 // New for WPA security suites
476 UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5
477 NDIS_802_11_VARIABLE_IEs *pVIE = NULL;
478 LARGE_INTEGER TimeStamp;
479 BOOLEAN Privacy;
480 USHORT Status;
482 // Init Variable IE structure
483 pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
484 pVIE->Length = 0;
485 TimeStamp.u.LowPart = 0;
486 TimeStamp.u.HighPart = 0;
488 if (MlmeStartReqSanity(pAd, Elem->Msg, Elem->MsgLen, Ssid, &SsidLen))
490 // reset all the timers
491 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled);
492 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
495 // Start a new IBSS. All IBSS parameters are decided now....
497 DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqAction - Start a new IBSS. All IBSS parameters are decided now.... \n"));
498 pAd->MlmeAux.BssType = BSS_ADHOC;
499 NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen);
500 pAd->MlmeAux.SsidLen = SsidLen;
502 // generate a radom number as BSSID
503 MacAddrRandomBssid(pAd, pAd->MlmeAux.Bssid);
504 DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqAction - generate a radom number as BSSID \n"));
506 Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) ||
507 (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) ||
508 (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled);
509 pAd->MlmeAux.CapabilityInfo = CAP_GENERATE(0,1,Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 1, 0);
510 pAd->MlmeAux.BeaconPeriod = pAd->CommonCfg.BeaconPeriod;
511 pAd->MlmeAux.AtimWin = pAd->StaCfg.AtimWin;
512 pAd->MlmeAux.Channel = pAd->CommonCfg.Channel;
514 pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel;
515 pAd->MlmeAux.CentralChannel = pAd->CommonCfg.CentralChannel;
517 pAd->MlmeAux.SupRateLen= pAd->CommonCfg.SupRateLen;
518 NdisMoveMemory(pAd->MlmeAux.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
519 RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen);
520 pAd->MlmeAux.ExtRateLen = pAd->CommonCfg.ExtRateLen;
521 NdisMoveMemory(pAd->MlmeAux.ExtRate, pAd->CommonCfg.ExtRate, MAX_LEN_OF_SUPPORTED_RATES);
522 RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen);
524 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
526 RTMPUpdateHTIE(&pAd->CommonCfg.DesiredHtPhy, &pAd->StaCfg.DesiredHtPhyInfo.MCSSet[0], &pAd->MlmeAux.HtCapability, &pAd->MlmeAux.AddHtInfo);
527 pAd->MlmeAux.HtCapabilityLen = sizeof(HT_CAPABILITY_IE);
528 // Not turn pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE here.
529 DBGPRINT(RT_DEBUG_TRACE, ("SYNC -pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE\n"));
531 else
533 pAd->MlmeAux.HtCapabilityLen = 0;
534 pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE;
536 // temporarily not support QOS in IBSS
537 NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(EDCA_PARM));
538 NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM));
539 NdisZeroMemory(&pAd->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM));
541 AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE);
542 AsicLockChannel(pAd, pAd->MlmeAux.Channel);
544 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeStartReqAction(ch= %d,sup rates= %d, ext rates=%d)\n",
545 pAd->MlmeAux.Channel, pAd->MlmeAux.SupRateLen, pAd->MlmeAux.ExtRateLen));
547 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
548 Status = MLME_SUCCESS;
549 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status);
551 else
553 DBGPRINT_ERR(("SYNC - MlmeStartReqAction() sanity check fail.\n"));
554 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
555 Status = MLME_INVALID_FORMAT;
556 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status);
561 ==========================================================================
562 Description:
563 peer sends beacon back when scanning
564 ==========================================================================
566 VOID PeerBeaconAtScanAction(
567 IN PRTMP_ADAPTER pAd,
568 IN MLME_QUEUE_ELEM *Elem)
570 UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN];
571 UCHAR Ssid[MAX_LEN_OF_SSID], BssType, Channel, NewChannel,
572 SsidLen, DtimCount, DtimPeriod, BcastFlag, MessageToMe;
573 CF_PARM CfParm;
574 USHORT BeaconPeriod, AtimWin, CapabilityInfo;
575 PFRAME_802_11 pFrame;
576 LARGE_INTEGER TimeStamp;
577 UCHAR Erp;
578 UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
579 UCHAR SupRateLen, ExtRateLen;
580 USHORT LenVIE;
581 UCHAR CkipFlag;
582 UCHAR AironetCellPowerLimit;
583 EDCA_PARM EdcaParm;
584 QBSS_LOAD_PARM QbssLoad;
585 QOS_CAPABILITY_PARM QosCapability;
586 ULONG RalinkIe;
587 UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5
588 NDIS_802_11_VARIABLE_IEs *pVIE = NULL;
589 HT_CAPABILITY_IE HtCapability;
590 ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE
591 UCHAR HtCapabilityLen = 0, PreNHtCapabilityLen = 0;
592 UCHAR AddHtInfoLen;
593 UCHAR NewExtChannelOffset = 0xff;
595 pFrame = (PFRAME_802_11) Elem->Msg;
596 // Init Variable IE structure
597 pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
598 pVIE->Length = 0;
600 RTMPZeroMemory(&HtCapability, sizeof(HtCapability));
601 RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE));
603 if (PeerBeaconAndProbeRspSanity(pAd,
604 Elem->Msg,
605 Elem->MsgLen,
606 Elem->Channel,
607 Addr2,
608 Bssid,
609 Ssid,
610 &SsidLen,
611 &BssType,
612 &BeaconPeriod,
613 &Channel,
614 &NewChannel,
615 &TimeStamp,
616 &CfParm,
617 &AtimWin,
618 &CapabilityInfo,
619 &Erp,
620 &DtimCount,
621 &DtimPeriod,
622 &BcastFlag,
623 &MessageToMe,
624 SupRate,
625 &SupRateLen,
626 ExtRate,
627 &ExtRateLen,
628 &CkipFlag,
629 &AironetCellPowerLimit,
630 &EdcaParm,
631 &QbssLoad,
632 &QosCapability,
633 &RalinkIe,
634 &HtCapabilityLen,
635 &PreNHtCapabilityLen,
636 &HtCapability,
637 &AddHtInfoLen,
638 &AddHtInfo,
639 &NewExtChannelOffset,
640 &LenVIE,
641 pVIE))
643 ULONG Idx;
644 CHAR Rssi = 0;
646 Idx = BssTableSearch(&pAd->ScanTab, Bssid, Channel);
647 if (Idx != BSS_NOT_FOUND)
648 Rssi = pAd->ScanTab.BssEntry[Idx].Rssi;
650 Rssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
652 if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0))
653 HtCapabilityLen = SIZE_HT_CAP_IE;
655 if ((pAd->StaCfg.CCXReqType != MSRN_TYPE_UNUSED) && (Channel == pAd->StaCfg.CCXScanChannel))
657 Idx = BssTableSetEntry(pAd, &pAd->StaCfg.CCXBssTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod,
658 &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen,ExtRate, ExtRateLen, &HtCapability,
659 &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, Rssi, TimeStamp, CkipFlag,
660 &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE);
661 if (Idx != BSS_NOT_FOUND)
663 NdisMoveMemory(pAd->StaCfg.CCXBssTab.BssEntry[Idx].PTSF, &Elem->Msg[24], 4);
664 NdisMoveMemory(&pAd->StaCfg.CCXBssTab.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4);
665 NdisMoveMemory(&pAd->StaCfg.CCXBssTab.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4);
666 if (pAd->StaCfg.CCXReqType == MSRN_TYPE_BEACON_REQ)
667 AironetAddBeaconReport(pAd, Idx, Elem);
670 else
672 Idx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod,
673 &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability,
674 &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, Rssi, TimeStamp, CkipFlag,
675 &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE);
677 if (Idx != BSS_NOT_FOUND)
679 NdisMoveMemory(pAd->ScanTab.BssEntry[Idx].PTSF, &Elem->Msg[24], 4);
680 NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4);
681 NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4);
685 // sanity check fail, ignored
689 ==========================================================================
690 Description:
691 When waiting joining the (I)BSS, beacon received from external
692 ==========================================================================
694 VOID PeerBeaconAtJoinAction(
695 IN PRTMP_ADAPTER pAd,
696 IN MLME_QUEUE_ELEM *Elem)
698 UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN];
699 UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, BssType, Channel, MessageToMe,
700 DtimCount, DtimPeriod, BcastFlag, NewChannel;
701 LARGE_INTEGER TimeStamp;
702 USHORT BeaconPeriod, AtimWin, CapabilityInfo;
703 CF_PARM Cf;
704 BOOLEAN TimerCancelled;
705 UCHAR Erp;
706 UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
707 UCHAR SupRateLen, ExtRateLen;
708 UCHAR CkipFlag;
709 USHORT LenVIE;
710 UCHAR AironetCellPowerLimit;
711 EDCA_PARM EdcaParm;
712 QBSS_LOAD_PARM QbssLoad;
713 QOS_CAPABILITY_PARM QosCapability;
714 USHORT Status;
715 UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5
716 NDIS_802_11_VARIABLE_IEs *pVIE = NULL;
717 ULONG RalinkIe;
718 ULONG Idx;
719 HT_CAPABILITY_IE HtCapability;
720 ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE
721 UCHAR HtCapabilityLen = 0, PreNHtCapabilityLen = 0;
722 UCHAR AddHtInfoLen;
723 UCHAR NewExtChannelOffset = 0xff;
724 UCHAR CentralChannel;
726 // Init Variable IE structure
727 pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
728 pVIE->Length = 0;
729 RTMPZeroMemory(&HtCapability, sizeof(HtCapability));
730 RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE));
733 if (PeerBeaconAndProbeRspSanity(pAd,
734 Elem->Msg,
735 Elem->MsgLen,
736 Elem->Channel,
737 Addr2,
738 Bssid,
739 Ssid,
740 &SsidLen,
741 &BssType,
742 &BeaconPeriod,
743 &Channel,
744 &NewChannel,
745 &TimeStamp,
746 &Cf,
747 &AtimWin,
748 &CapabilityInfo,
749 &Erp,
750 &DtimCount,
751 &DtimPeriod,
752 &BcastFlag,
753 &MessageToMe,
754 SupRate,
755 &SupRateLen,
756 ExtRate,
757 &ExtRateLen,
758 &CkipFlag,
759 &AironetCellPowerLimit,
760 &EdcaParm,
761 &QbssLoad,
762 &QosCapability,
763 &RalinkIe,
764 &HtCapabilityLen,
765 &PreNHtCapabilityLen,
766 &HtCapability,
767 &AddHtInfoLen,
768 &AddHtInfo,
769 &NewExtChannelOffset,
770 &LenVIE,
771 pVIE))
773 // Disqualify 11b only adhoc when we are in 11g only adhoc mode
774 if ((BssType == BSS_ADHOC) && (pAd->CommonCfg.PhyMode == PHY_11G) && ((SupRateLen+ExtRateLen)< 12))
775 return;
777 // BEACON from desired BSS/IBSS found. We should be able to decide most
778 // BSS parameters here.
779 // Q. But what happen if this JOIN doesn't conclude a successful ASSOCIATEION?
780 // Do we need to receover back all parameters belonging to previous BSS?
781 // A. Should be not. There's no back-door recover to previous AP. It still need
782 // a new JOIN-AUTH-ASSOC sequence.
783 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Bssid))
785 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - receive desired BEACON at JoinWaitBeacon... Channel = %d\n", Channel));
786 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
788 // Update RSSI to prevent No signal display when cards first initialized
789 pAd->StaCfg.RssiSample.LastRssi0 = ConvertToRssi(pAd, Elem->Rssi0, RSSI_0);
790 pAd->StaCfg.RssiSample.LastRssi1 = ConvertToRssi(pAd, Elem->Rssi1, RSSI_1);
791 pAd->StaCfg.RssiSample.LastRssi2 = ConvertToRssi(pAd, Elem->Rssi2, RSSI_2);
792 pAd->StaCfg.RssiSample.AvgRssi0 = pAd->StaCfg.RssiSample.LastRssi0;
793 pAd->StaCfg.RssiSample.AvgRssi0X8 = pAd->StaCfg.RssiSample.AvgRssi0 << 3;
794 pAd->StaCfg.RssiSample.AvgRssi1 = pAd->StaCfg.RssiSample.LastRssi1;
795 pAd->StaCfg.RssiSample.AvgRssi1X8 = pAd->StaCfg.RssiSample.AvgRssi1 << 3;
796 pAd->StaCfg.RssiSample.AvgRssi2 = pAd->StaCfg.RssiSample.LastRssi2;
797 pAd->StaCfg.RssiSample.AvgRssi2X8 = pAd->StaCfg.RssiSample.AvgRssi2 << 3;
800 // We need to check if SSID only set to any, then we can record the current SSID.
801 // Otherwise will cause hidden SSID association failed.
803 if (pAd->MlmeAux.SsidLen == 0)
805 NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen);
806 pAd->MlmeAux.SsidLen = SsidLen;
808 else
810 Idx = BssSsidTableSearch(&pAd->ScanTab, Bssid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Channel);
812 if (Idx != BSS_NOT_FOUND)
815 // Multiple SSID case, used correct CapabilityInfo
817 CapabilityInfo = pAd->ScanTab.BssEntry[Idx].CapabilityInfo;
820 NdisMoveMemory(pAd->MlmeAux.Bssid, Bssid, MAC_ADDR_LEN);
821 pAd->MlmeAux.CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO;
822 pAd->MlmeAux.BssType = BssType;
823 pAd->MlmeAux.BeaconPeriod = BeaconPeriod;
824 pAd->MlmeAux.Channel = Channel;
825 pAd->MlmeAux.AtimWin = AtimWin;
826 pAd->MlmeAux.CfpPeriod = Cf.CfpPeriod;
827 pAd->MlmeAux.CfpMaxDuration = Cf.CfpMaxDuration;
828 pAd->MlmeAux.APRalinkIe = RalinkIe;
830 // Copy AP's supported rate to MlmeAux for creating assoication request
831 // Also filter out not supported rate
832 pAd->MlmeAux.SupRateLen = SupRateLen;
833 NdisMoveMemory(pAd->MlmeAux.SupRate, SupRate, SupRateLen);
834 RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen);
835 pAd->MlmeAux.ExtRateLen = ExtRateLen;
836 NdisMoveMemory(pAd->MlmeAux.ExtRate, ExtRate, ExtRateLen);
837 RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen);
839 NdisZeroMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, 16);
841 pAd->MlmeAux.NewExtChannelOffset = NewExtChannelOffset;
842 pAd->MlmeAux.HtCapabilityLen = HtCapabilityLen;
844 // filter out un-supported ht rates
845 if (((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
847 RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE);
848 RTMPMoveMemory(&pAd->MlmeAux.AddHtInfo, &AddHtInfo, SIZE_ADD_HT_INFO_IE);
850 // StaActive.SupportedHtPhy.MCSSet stores Peer AP's 11n Rx capability
851 NdisMoveMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, HtCapability.MCSSet, 16);
852 pAd->MlmeAux.NewExtChannelOffset = NewExtChannelOffset;
853 pAd->MlmeAux.HtCapabilityLen = SIZE_HT_CAP_IE;
854 pAd->StaActive.SupportedPhyInfo.bHtEnable = TRUE;
855 if (PreNHtCapabilityLen > 0)
856 pAd->StaActive.SupportedPhyInfo.bPreNHt = TRUE;
857 RTMPCheckHt(pAd, BSSID_WCID, &HtCapability, &AddHtInfo);
858 // Copy AP Parameter to StaActive. This is also in LinkUp.
859 DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction! (MpduDensity=%d, MaxRAmpduFactor=%d, BW=%d)\n",
860 pAd->StaActive.SupportedHtPhy.MpduDensity, pAd->StaActive.SupportedHtPhy.MaxRAmpduFactor, HtCapability.HtCapInfo.ChannelWidth));
862 if (AddHtInfoLen > 0)
864 CentralChannel = AddHtInfo.ControlChan;
865 // Check again the Bandwidth capability of this AP.
866 if ((AddHtInfo.ControlChan > 2)&& (AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (HtCapability.HtCapInfo.ChannelWidth == BW_40))
868 CentralChannel = AddHtInfo.ControlChan - 2;
870 else if ((AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (HtCapability.HtCapInfo.ChannelWidth == BW_40))
872 CentralChannel = AddHtInfo.ControlChan + 2;
875 // Check Error .
876 if (pAd->MlmeAux.CentralChannel != CentralChannel)
877 DBGPRINT(RT_DEBUG_ERROR, ("PeerBeaconAtJoinAction HT===>Beacon Central Channel = %d, Control Channel = %d. Mlmeaux CentralChannel = %d\n", CentralChannel, AddHtInfo.ControlChan, pAd->MlmeAux.CentralChannel));
879 DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction HT===>Central Channel = %d, Control Channel = %d, .\n", CentralChannel, AddHtInfo.ControlChan));
884 else
886 // To prevent error, let legacy AP must have same CentralChannel and Channel.
887 if ((HtCapabilityLen == 0) && (PreNHtCapabilityLen == 0))
888 pAd->MlmeAux.CentralChannel = pAd->MlmeAux.Channel;
890 pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE;
891 RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE);
892 RTMPZeroMemory(&pAd->MlmeAux.AddHtInfo, SIZE_ADD_HT_INFO_IE);
895 RTMPUpdateMlmeRate(pAd);
897 // copy QOS related information
898 if ((pAd->CommonCfg.bWmmCapable)
899 || (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
902 NdisMoveMemory(&pAd->MlmeAux.APEdcaParm, &EdcaParm, sizeof(EDCA_PARM));
903 NdisMoveMemory(&pAd->MlmeAux.APQbssLoad, &QbssLoad, sizeof(QBSS_LOAD_PARM));
904 NdisMoveMemory(&pAd->MlmeAux.APQosCapability, &QosCapability, sizeof(QOS_CAPABILITY_PARM));
906 else
908 NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(EDCA_PARM));
909 NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM));
910 NdisZeroMemory(&pAd->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM));
913 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - after JOIN, SupRateLen=%d, ExtRateLen=%d\n",
914 pAd->MlmeAux.SupRateLen, pAd->MlmeAux.ExtRateLen));
916 if (AironetCellPowerLimit != 0xFF)
918 //We need to change our TxPower for CCX 2.0 AP Control of Client Transmit Power
919 ChangeToCellPowerLimit(pAd, AironetCellPowerLimit);
921 else //Used the default TX Power Percentage.
922 pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault;
924 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
925 Status = MLME_SUCCESS;
926 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status);
928 // not to me BEACON, ignored
930 // sanity check fail, ignore this frame
934 ==========================================================================
935 Description:
936 receive BEACON from peer
938 IRQL = DISPATCH_LEVEL
940 ==========================================================================
942 VOID PeerBeacon(
943 IN PRTMP_ADAPTER pAd,
944 IN MLME_QUEUE_ELEM *Elem)
946 UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN];
947 CHAR Ssid[MAX_LEN_OF_SSID];
948 CF_PARM CfParm;
949 UCHAR SsidLen, MessageToMe=0, BssType, Channel, NewChannel, index=0;
950 UCHAR DtimCount=0, DtimPeriod=0, BcastFlag=0;
951 USHORT CapabilityInfo, AtimWin, BeaconPeriod;
952 LARGE_INTEGER TimeStamp;
953 USHORT TbttNumToNextWakeUp;
954 UCHAR Erp;
955 UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
956 UCHAR SupRateLen, ExtRateLen;
957 UCHAR CkipFlag;
958 USHORT LenVIE;
959 UCHAR AironetCellPowerLimit;
960 EDCA_PARM EdcaParm;
961 QBSS_LOAD_PARM QbssLoad;
962 QOS_CAPABILITY_PARM QosCapability;
963 ULONG RalinkIe;
964 // New for WPA security suites
965 UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5
966 NDIS_802_11_VARIABLE_IEs *pVIE = NULL;
967 HT_CAPABILITY_IE HtCapability;
968 ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE
969 UCHAR HtCapabilityLen, PreNHtCapabilityLen;
970 UCHAR AddHtInfoLen;
971 UCHAR NewExtChannelOffset = 0xff;
973 if (!(INFRA_ON(pAd) || ADHOC_ON(pAd)
975 return;
977 // Init Variable IE structure
978 pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
979 pVIE->Length = 0;
980 RTMPZeroMemory(&HtCapability, sizeof(HtCapability));
981 RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE));
983 if (PeerBeaconAndProbeRspSanity(pAd,
984 Elem->Msg,
985 Elem->MsgLen,
986 Elem->Channel,
987 Addr2,
988 Bssid,
989 Ssid,
990 &SsidLen,
991 &BssType,
992 &BeaconPeriod,
993 &Channel,
994 &NewChannel,
995 &TimeStamp,
996 &CfParm,
997 &AtimWin,
998 &CapabilityInfo,
999 &Erp,
1000 &DtimCount,
1001 &DtimPeriod,
1002 &BcastFlag,
1003 &MessageToMe,
1004 SupRate,
1005 &SupRateLen,
1006 ExtRate,
1007 &ExtRateLen,
1008 &CkipFlag,
1009 &AironetCellPowerLimit,
1010 &EdcaParm,
1011 &QbssLoad,
1012 &QosCapability,
1013 &RalinkIe,
1014 &HtCapabilityLen,
1015 &PreNHtCapabilityLen,
1016 &HtCapability,
1017 &AddHtInfoLen,
1018 &AddHtInfo,
1019 &NewExtChannelOffset,
1020 &LenVIE,
1021 pVIE))
1023 BOOLEAN is_my_bssid, is_my_ssid;
1024 ULONG Bssidx, Now;
1025 BSS_ENTRY *pBss;
1026 CHAR RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
1028 is_my_bssid = MAC_ADDR_EQUAL(Bssid, pAd->CommonCfg.Bssid)? TRUE : FALSE;
1029 is_my_ssid = SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)? TRUE:FALSE;
1032 // ignore BEACON not for my SSID
1033 if ((! is_my_ssid) && (! is_my_bssid))
1034 return;
1036 // It means STA waits disassoc completely from this AP, ignores this beacon.
1037 if (pAd->Mlme.CntlMachine.CurrState == CNTL_WAIT_DISASSOC)
1038 return;
1040 // Copy Control channel for this BSSID.
1041 if (AddHtInfoLen != 0)
1042 Channel = AddHtInfo.ControlChan;
1044 if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0))
1045 HtCapabilityLen = SIZE_HT_CAP_IE;
1048 // Housekeeping "SsidBssTab" table for later-on ROAMing usage.
1050 Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel);
1051 if (Bssidx == BSS_NOT_FOUND)
1053 // discover new AP of this network, create BSS entry
1054 Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod,
1055 &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,
1056 &HtCapability, &AddHtInfo,HtCapabilityLen,AddHtInfoLen,NewExtChannelOffset, Channel,
1057 RealRssi, TimeStamp, CkipFlag, &EdcaParm, &QosCapability,
1058 &QbssLoad, LenVIE, pVIE);
1059 if (Bssidx == BSS_NOT_FOUND) // return if BSS table full
1060 return;
1062 NdisMoveMemory(pAd->ScanTab.BssEntry[Bssidx].PTSF, &Elem->Msg[24], 4);
1063 NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4);
1064 NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4);
1070 if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel))
1072 // Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection).
1073 // In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results.
1074 AsicSwitchChannel(pAd, 1, FALSE);
1075 AsicLockChannel(pAd, 1);
1076 LinkDown(pAd, FALSE);
1077 MlmeQueueInit(&pAd->Mlme.Queue);
1078 BssTableInit(&pAd->ScanTab);
1079 RTMPusecDelay(1000000); // use delay to prevent STA do reassoc
1081 // channel sanity check
1082 for (index = 0 ; index < pAd->ChannelListNum; index++)
1084 if (pAd->ChannelList[index].Channel == NewChannel)
1086 pAd->ScanTab.BssEntry[Bssidx].Channel = NewChannel;
1087 pAd->CommonCfg.Channel = NewChannel;
1088 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
1089 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
1090 DBGPRINT(RT_DEBUG_TRACE, ("PeerBeacon - STA receive channel switch announcement IE (New Channel =%d)\n", NewChannel));
1091 break;
1095 if (index >= pAd->ChannelListNum)
1097 DBGPRINT_ERR(("PeerBeacon(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum));
1101 // if the ssid matched & bssid unmatched, we should select the bssid with large value.
1102 // This might happened when two STA start at the same time
1103 if ((! is_my_bssid) && ADHOC_ON(pAd))
1105 INT i;
1107 // Add the safeguard against the mismatch of adhoc wep status
1108 if (pAd->StaCfg.WepStatus != pAd->ScanTab.BssEntry[Bssidx].WepStatus)
1110 return;
1113 // collapse into the ADHOC network which has bigger BSSID value.
1114 for (i = 0; i < 6; i++)
1116 if (Bssid[i] > pAd->CommonCfg.Bssid[i])
1118 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - merge to the IBSS with bigger BSSID=%02x:%02x:%02x:%02x:%02x:%02x\n",
1119 Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5]));
1120 AsicDisableSync(pAd);
1121 COPY_MAC_ADDR(pAd->CommonCfg.Bssid, Bssid);
1122 AsicSetBssid(pAd, pAd->CommonCfg.Bssid);
1123 MakeIbssBeacon(pAd); // re-build BEACON frame
1124 AsicEnableIbssSync(pAd); // copy BEACON frame to on-chip memory
1125 is_my_bssid = TRUE;
1126 break;
1128 else if (Bssid[i] < pAd->CommonCfg.Bssid[i])
1129 break;
1134 NdisGetSystemUpTime(&Now);
1135 pBss = &pAd->ScanTab.BssEntry[Bssidx];
1136 pBss->Rssi = RealRssi; // lastest RSSI
1137 pBss->LastBeaconRxTime = Now; // last RX timestamp
1140 // BEACON from my BSSID - either IBSS or INFRA network
1142 if (is_my_bssid)
1144 RXWI_STRUC RxWI;
1146 pAd->StaCfg.DtimCount = DtimCount;
1147 pAd->StaCfg.DtimPeriod = DtimPeriod;
1148 pAd->StaCfg.LastBeaconRxTime = Now;
1151 RxWI.RSSI0 = Elem->Rssi0;
1152 RxWI.RSSI1 = Elem->Rssi1;
1153 RxWI.RSSI2 = Elem->Rssi2;
1155 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, &RxWI);
1156 if (AironetCellPowerLimit != 0xFF)
1159 // We get the Cisco (ccx) "TxPower Limit" required
1160 // Changed to appropriate TxPower Limit for Ciso Compatible Extensions
1162 ChangeToCellPowerLimit(pAd, AironetCellPowerLimit);
1164 else
1167 // AironetCellPowerLimit equal to 0xFF means the Cisco (ccx) "TxPower Limit" not exist.
1168 // Used the default TX Power Percentage, that set from UI.
1170 pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault;
1173 // at least one 11b peer joined. downgrade the MaxTxRate to 11Mbps
1174 // after last 11b peer left for several seconds, we'll auto switch back to 11G rate
1175 // in MlmePeriodicExec()
1176 if (ADHOC_ON(pAd) && (CAP_IS_IBSS_ON(CapabilityInfo)))
1178 BOOLEAN bRestart;
1179 BOOLEAN bnRestart;
1181 bRestart = FALSE;
1182 bnRestart = FALSE;
1186 if ((SupRateLen+ExtRateLen <= 4) && (pAd->CommonCfg.MaxTxRate > RATE_11))
1188 if (pAd->StaCfg.AdhocBOnlyJoined == FALSE)
1190 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - 11b peer joined. down-grade to 11b TX rates \n"));
1191 bRestart = TRUE;
1192 NdisMoveMemory(pAd->StaActive.SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
1193 pAd->StaActive.SupRateLen = SupRateLen;
1194 NdisMoveMemory(pAd->StaActive.ExtRate, ExtRate, MAX_LEN_OF_SUPPORTED_RATES);
1195 pAd->StaActive.ExtRateLen = ExtRateLen;
1196 pAd->StaCfg.AdhocBOnlyJoined = TRUE;
1197 pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE;
1198 AsicSetEdcaParm(pAd, NULL);
1201 // this timestamp is for MlmePeriodicExec() to check if all 11B peers have left
1202 pAd->StaCfg.Last11bBeaconRxTime = Now;
1203 break;
1206 // Update Ht Phy.
1207 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
1209 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) &&
1210 !pAd->StaCfg.AdhocBGJoined &&
1211 !pAd->StaCfg.AdhocBOnlyJoined)
1212 AdhocTurnOnQos(pAd);
1214 // Handle rate switch issue when Adhoc mode
1215 if ((SupRateLen+ExtRateLen >= 8) && (HtCapability.MCSSet[0] == 0) && (HtCapability.MCSSet[1] == 0))
1217 if (pAd->StaCfg.AdhocBGJoined == FALSE)
1219 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - 11g peer joined. down-grade to 11g TX rates \n"));
1220 bRestart = TRUE;
1221 NdisMoveMemory(pAd->StaActive.SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
1222 pAd->StaActive.SupRateLen = SupRateLen;
1223 NdisMoveMemory(pAd->StaActive.ExtRate, ExtRate, MAX_LEN_OF_SUPPORTED_RATES);
1224 pAd->StaActive.ExtRateLen = ExtRateLen;
1225 pAd->StaCfg.AdhocBGJoined = TRUE;
1226 pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE;
1227 AsicSetEdcaParm(pAd, NULL);
1230 // this timestamp is for MlmePeriodicExec() to check if all 11g peers have left
1231 pAd->StaCfg.Last11gBeaconRxTime = Now;
1232 break;
1234 else if (!pAd->StaCfg.AdhocBGJoined &&
1235 !pAd->StaCfg.AdhocBOnlyJoined &&
1236 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) &&
1237 (HtCapability.HtCapInfo.ChannelWidth == BW_20))
1239 if (pAd->StaCfg.Adhoc20NJoined == FALSE)
1241 pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel;
1243 pAd->StaCfg.Adhoc20NJoined = TRUE;
1244 NdisMoveMemory(&pAd->MlmeAux.HtCapability, &HtCapability, SIZE_HT_CAP_IE);
1245 if (AddHtInfoLen != 0)
1246 NdisMoveMemory(&pAd->MlmeAux.AddHtInfo, &AddHtInfo, AddHtInfoLen);
1247 NdisMoveMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, HtCapability.MCSSet, 16);
1249 RTMPCheckHt(pAd, Elem->Wcid, &pAd->MlmeAux.HtCapability, &pAd->MlmeAux.AddHtInfo);
1250 COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd);
1251 pAd->StaActive.SupportedPhyInfo.bHtEnable = TRUE;
1252 bRestart = TRUE;
1253 bnRestart = TRUE;
1255 // this timestamp is for MlmePeriodicExec() to check if all 20MHz N peers have left
1256 pAd->StaCfg.Last20NBeaconRxTime = Now;
1260 else
1262 RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE);
1263 RTMPZeroMemory(&pAd->MlmeAux.AddHtInfo, SIZE_ADD_HT_INFO_IE);
1265 }while (FALSE);
1267 // If peer Adhoc is legacy mode, I don't need to call MlmeUpdateHtTxRates no matter I support HT or not
1268 if ((bRestart == TRUE) && (bnRestart == FALSE))
1270 MlmeUpdateTxRates(pAd, FALSE, 0);
1271 MakeIbssBeacon(pAd); // re-build BEACON frame
1272 AsicEnableIbssSync(pAd); // copy to on-chip memory
1274 else if ((bRestart == TRUE) && (bnRestart == TRUE))
1276 MlmeUpdateTxRates(pAd, FALSE, BSS0);
1277 MlmeUpdateHtTxRates(pAd, BSS0);
1278 MakeIbssBeacon(pAd); // re-build BEACON frame
1279 AsicEnableIbssSync(pAd); // copy to on-chip memory
1282 // At least another peer in this IBSS, declare MediaState as CONNECTED
1283 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1285 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
1287 pAd->IndicateMediaState = NdisMediaStateConnected;
1288 RTMP_IndicateMediaState(pAd);
1289 pAd->ExtraInfo = GENERAL_LINK_UP;
1290 AsicSetBssid(pAd, pAd->CommonCfg.Bssid);
1292 // 2003/03/12 - john
1293 // Make sure this entry in "ScanTab" table, thus complies to Microsoft's policy that
1294 // "site survey" result should always include the current connected network.
1296 Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel);
1297 if (Bssidx == BSS_NOT_FOUND)
1299 Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod,
1300 &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability,
1301 &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, RealRssi, TimeStamp, 0,
1302 &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE);
1304 DBGPRINT(RT_DEBUG_TRACE, ("ADHOC fOP_STATUS_MEDIA_STATE_CONNECTED.\n"));
1307 // Ad-hoc mode is using MAC address as BA session. So we need to continuously find newly joined adhoc station by receiving beacon.
1308 // To prevent always check this, we use wcid == RESERVED_WCID to recognize it as newly joined adhoc station.
1309 if (ADHOC_ON(pAd) && (Elem->Wcid == RESERVED_WCID))
1311 UCHAR idx;
1312 MAC_TABLE_ENTRY *pEntry;
1314 // look up the existing table
1315 pEntry = MacTableLookup(pAd, Addr2);
1316 if (pEntry == NULL)
1318 // Another adhoc joining, add to our MAC table.
1319 pEntry = MacTableInsertEntry(pAd, Addr2, BSS0, FALSE);
1320 if (pEntry)
1322 pEntry->Sst = SST_ASSOC;
1323 idx = pAd->StaCfg.DefaultKeyId;
1324 // After InsertEntry, Write to ASIC on-chip table.
1325 RT28XX_STA_SECURITY_INFO_ADD(pAd, BSS0, idx, pEntry);
1326 DBGPRINT(RT_DEBUG_TRACE, ("ADHOC %x:%x:%x:%x:%x:%x join in.Entry=%d\n", Addr2[0],Addr2[1],Addr2[2],Addr2[3],Addr2[4],Addr2[5], pEntry->Aid));
1328 pEntry->HTPhyMode.word = pAd->StaCfg.HTPhyMode.word;
1329 if (HtCapabilityLen <= 0)
1331 pEntry->HTPhyMode.field.STBC = 0;
1332 pEntry->HTPhyMode.field.BW = 0;
1333 pEntry->HTPhyMode.field.ShortGI = 0;
1334 if ((SupRateLen+ExtRateLen <= 4) && (pAd->CommonCfg.Channel <= 14))
1336 pEntry->HTPhyMode.field.MODE = MODE_CCK;
1338 else
1340 pEntry->HTPhyMode.field.MODE = MODE_OFDM;
1342 MlmeUpdateTxRates(pAd, FALSE, 0);
1344 else
1346 MlmeUpdateTxRates(pAd, FALSE, 0);
1347 MlmeUpdateHtTxRates(pAd, BSS0);
1351 union iwreq_data wrqu;
1352 wext_notify_event_assoc(pAd);
1354 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1355 memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN);
1356 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1364 if (INFRA_ON(pAd))
1366 BOOLEAN bUseShortSlot, bUseBGProtection;
1368 // decide to use/change to -
1369 // 1. long slot (20 us) or short slot (9 us) time
1370 // 2. turn on/off RTS/CTS and/or CTS-to-self protection
1371 // 3. short preamble
1373 //bUseShortSlot = pAd->CommonCfg.bUseShortSlotTime && CAP_IS_SHORT_SLOT(CapabilityInfo);
1374 bUseShortSlot = CAP_IS_SHORT_SLOT(CapabilityInfo);
1375 if (bUseShortSlot != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED))
1376 AsicSetSlotTime(pAd, bUseShortSlot);
1378 bUseBGProtection = (pAd->CommonCfg.UseBGProtection == 1) || // always use
1379 ((pAd->CommonCfg.UseBGProtection == 0) && ERP_IS_USE_PROTECTION(Erp));
1381 if (pAd->CommonCfg.Channel > 14) // always no BG protection in A-band. falsely happened when switching A/G band to a dual-band AP
1382 bUseBGProtection = FALSE;
1384 if (bUseBGProtection != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
1386 if (bUseBGProtection)
1388 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED);
1389 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, (OFDMSETPROTECT|CCKSETPROTECT|ALLN_SETPROTECT),FALSE,(pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1));
1391 else
1393 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED);
1394 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, (OFDMSETPROTECT|CCKSETPROTECT|ALLN_SETPROTECT),TRUE,(pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1));
1397 DBGPRINT(RT_DEBUG_WARN, ("SYNC - AP changed B/G protection to %d\n", bUseBGProtection));
1400 // check Ht protection mode. and adhere to the Non-GF device indication by AP.
1401 if ((AddHtInfoLen != 0) &&
1402 ((AddHtInfo.AddHtInfo2.OperaionMode != pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode) ||
1403 (AddHtInfo.AddHtInfo2.NonGfPresent != pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent)))
1405 pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent = AddHtInfo.AddHtInfo2.NonGfPresent;
1406 pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode = AddHtInfo.AddHtInfo2.OperaionMode;
1407 if (pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1)
1409 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, TRUE);
1411 else
1412 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1414 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP changed N OperaionMode to %d\n", pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode));
1417 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED) &&
1418 ERP_IS_USE_BARKER_PREAMBLE(Erp))
1420 MlmeSetTxPreamble(pAd, Rt802_11PreambleLong);
1421 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP forced to use LONG preamble\n"));
1424 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
1425 (EdcaParm.bValid == TRUE) &&
1426 (EdcaParm.EdcaUpdateCount != pAd->CommonCfg.APEdcaParm.EdcaUpdateCount))
1428 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP change EDCA parameters(from %d to %d)\n",
1429 pAd->CommonCfg.APEdcaParm.EdcaUpdateCount,
1430 EdcaParm.EdcaUpdateCount));
1431 AsicSetEdcaParm(pAd, &EdcaParm);
1434 // copy QOS related information
1435 NdisMoveMemory(&pAd->CommonCfg.APQbssLoad, &QbssLoad, sizeof(QBSS_LOAD_PARM));
1436 NdisMoveMemory(&pAd->CommonCfg.APQosCapability, &QosCapability, sizeof(QOS_CAPABILITY_PARM));
1439 // only INFRASTRUCTURE mode support power-saving feature
1440 if ((INFRA_ON(pAd) && (pAd->StaCfg.Psm == PWR_SAVE)) || (pAd->CommonCfg.bAPSDForcePowerSave))
1442 UCHAR FreeNumber;
1443 // 1. AP has backlogged unicast-to-me frame, stay AWAKE, send PSPOLL
1444 // 2. AP has backlogged broadcast/multicast frame and we want those frames, stay AWAKE
1445 // 3. we have outgoing frames in TxRing or MgmtRing, better stay AWAKE
1446 // 4. Psm change to PWR_SAVE, but AP not been informed yet, we better stay AWAKE
1447 // 5. otherwise, put PHY back to sleep to save battery.
1448 if (MessageToMe)
1450 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
1452 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3);
1454 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable &&
1455 pAd->CommonCfg.bAPSDAC_BE && pAd->CommonCfg.bAPSDAC_BK && pAd->CommonCfg.bAPSDAC_VI && pAd->CommonCfg.bAPSDAC_VO)
1457 pAd->CommonCfg.bNeedSendTriggerFrame = TRUE;
1459 else
1460 RT28XX_PS_POLL_ENQUEUE(pAd);
1462 else if (BcastFlag && (DtimCount == 0) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM))
1464 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
1466 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3);
1469 else if ((pAd->TxSwQueue[QID_AC_BK].Number != 0) ||
1470 (pAd->TxSwQueue[QID_AC_BE].Number != 0) ||
1471 (pAd->TxSwQueue[QID_AC_VI].Number != 0) ||
1472 (pAd->TxSwQueue[QID_AC_VO].Number != 0) ||
1473 (RTMPFreeTXDRequest(pAd, QID_AC_BK, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) ||
1474 (RTMPFreeTXDRequest(pAd, QID_AC_BE, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) ||
1475 (RTMPFreeTXDRequest(pAd, QID_AC_VI, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) ||
1476 (RTMPFreeTXDRequest(pAd, QID_AC_VO, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) ||
1477 (RTMPFreeTXDRequest(pAd, QID_MGMT, MGMT_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS))
1479 // TODO: consider scheduled HCCA. might not be proper to use traditional DTIM-based power-saving scheme
1480 // can we cheat here (i.e. just check MGMT & AC_BE) for better performance?
1481 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
1483 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3);
1486 else
1488 USHORT NextDtim = DtimCount;
1490 if (NextDtim == 0)
1491 NextDtim = DtimPeriod;
1493 TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount;
1494 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim))
1495 TbttNumToNextWakeUp = NextDtim;
1497 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1499 // Set a flag to go to sleep . Then after parse this RxDoneInterrupt, will go to sleep mode.
1500 RTMP_SET_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW);
1501 pAd->ThisTbttNumToNextWakeUp = TbttNumToNextWakeUp;
1506 // not my BSSID, ignore it
1508 // sanity check fail, ignore this frame
1512 ==========================================================================
1513 Description:
1514 Receive PROBE REQ from remote peer when operating in IBSS mode
1515 ==========================================================================
1517 VOID PeerProbeReqAction(
1518 IN PRTMP_ADAPTER pAd,
1519 IN MLME_QUEUE_ELEM *Elem)
1521 UCHAR Addr2[MAC_ADDR_LEN];
1522 CHAR Ssid[MAX_LEN_OF_SSID];
1523 UCHAR SsidLen;
1524 UCHAR HtLen, AddHtLen, NewExtLen;
1525 HEADER_802_11 ProbeRspHdr;
1526 NDIS_STATUS NStatus;
1527 PUCHAR pOutBuffer = NULL;
1528 ULONG FrameLen = 0;
1529 LARGE_INTEGER FakeTimestamp;
1530 UCHAR DsLen = 1, IbssLen = 2;
1531 UCHAR LocalErpIe[3] = {IE_ERP, 1, 0};
1532 BOOLEAN Privacy;
1533 USHORT CapabilityInfo;
1534 UCHAR RSNIe = IE_WPA;
1536 if (! ADHOC_ON(pAd))
1537 return;
1539 if (PeerProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, Ssid, &SsidLen))
1541 if ((SsidLen == 0) || SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1543 // allocate and send out ProbeRsp frame
1544 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
1545 if (NStatus != NDIS_STATUS_SUCCESS)
1546 return;
1548 //pAd->StaCfg.AtimWin = 0; // ??????
1550 Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) ||
1551 (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) ||
1552 (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled);
1553 CapabilityInfo = CAP_GENERATE(0, 1, Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 0, 0);
1555 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1556 sizeof(HEADER_802_11), &ProbeRspHdr,
1557 TIMESTAMP_LEN, &FakeTimestamp,
1558 2, &pAd->CommonCfg.BeaconPeriod,
1559 2, &CapabilityInfo,
1560 1, &SsidIe,
1561 1, &pAd->CommonCfg.SsidLen,
1562 pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid,
1563 1, &SupRateIe,
1564 1, &pAd->StaActive.SupRateLen,
1565 pAd->StaActive.SupRateLen, pAd->StaActive.SupRate,
1566 1, &DsIe,
1567 1, &DsLen,
1568 1, &pAd->CommonCfg.Channel,
1569 1, &IbssIe,
1570 1, &IbssLen,
1571 2, &pAd->StaActive.AtimWin,
1572 END_OF_ARGS);
1574 if (pAd->StaActive.ExtRateLen)
1576 ULONG tmp;
1577 MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
1578 3, LocalErpIe,
1579 1, &ExtRateIe,
1580 1, &pAd->StaActive.ExtRateLen,
1581 pAd->StaActive.ExtRateLen, &pAd->StaActive.ExtRate,
1582 END_OF_ARGS);
1583 FrameLen += tmp;
1586 // If adhoc secruity is set for WPA-None, append the cipher suite IE
1587 if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone)
1589 ULONG tmp;
1590 MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
1591 1, &RSNIe,
1592 1, &pAd->StaCfg.RSNIE_Len,
1593 pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE,
1594 END_OF_ARGS);
1595 FrameLen += tmp;
1598 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
1600 ULONG TmpLen;
1601 UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33};
1602 HtLen = sizeof(pAd->CommonCfg.HtCapability);
1603 AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo);
1604 NewExtLen = 1;
1605 //New extension channel offset IE is included in Beacon, Probe Rsp or channel Switch Announcement Frame
1606 if (pAd->bBroadComHT == TRUE)
1608 MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
1609 1, &WpaIe,
1610 4, &BROADCOM[0],
1611 pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability,
1612 END_OF_ARGS);
1614 else
1616 MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
1617 1, &HtCapIe,
1618 1, &HtLen,
1619 sizeof(HT_CAPABILITY_IE), &pAd->CommonCfg.HtCapability,
1620 1, &AddHtInfoIe,
1621 1, &AddHtLen,
1622 sizeof(ADD_HT_INFO_IE), &pAd->CommonCfg.AddHTInfo,
1623 1, &NewExtChanIe,
1624 1, &NewExtLen,
1625 sizeof(NEW_EXT_CHAN_IE), &pAd->CommonCfg.NewExtChanOffset,
1626 END_OF_ARGS);
1628 FrameLen += TmpLen;
1631 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
1632 MlmeFreeMemory(pAd, pOutBuffer);
1637 VOID BeaconTimeoutAtJoinAction(
1638 IN PRTMP_ADAPTER pAd,
1639 IN MLME_QUEUE_ELEM *Elem)
1641 USHORT Status;
1642 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BeaconTimeoutAtJoinAction\n"));
1643 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1644 Status = MLME_REJ_TIMEOUT;
1645 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status);
1649 ==========================================================================
1650 Description:
1651 Scan timeout procedure. basically add channel index by 1 and rescan
1652 ==========================================================================
1654 VOID ScanTimeoutAction(
1655 IN PRTMP_ADAPTER pAd,
1656 IN MLME_QUEUE_ELEM *Elem)
1658 pAd->MlmeAux.Channel = NextChannel(pAd, pAd->MlmeAux.Channel);
1660 // Only one channel scanned for CISCO beacon request
1661 if ((pAd->MlmeAux.ScanType == SCAN_CISCO_ACTIVE) ||
1662 (pAd->MlmeAux.ScanType == SCAN_CISCO_PASSIVE) ||
1663 (pAd->MlmeAux.ScanType == SCAN_CISCO_NOISE) ||
1664 (pAd->MlmeAux.ScanType == SCAN_CISCO_CHANNEL_LOAD))
1665 pAd->MlmeAux.Channel = 0;
1667 // this routine will stop if pAd->MlmeAux.Channel == 0
1668 ScanNextChannel(pAd);
1672 ==========================================================================
1673 Description:
1674 ==========================================================================
1676 VOID InvalidStateWhenScan(
1677 IN PRTMP_ADAPTER pAd,
1678 IN MLME_QUEUE_ELEM *Elem)
1680 USHORT Status;
1681 DBGPRINT(RT_DEBUG_TRACE, ("AYNC - InvalidStateWhenScan(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState));
1682 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1683 Status = MLME_STATE_MACHINE_REJECT;
1684 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status);
1688 ==========================================================================
1689 Description:
1690 ==========================================================================
1692 VOID InvalidStateWhenJoin(
1693 IN PRTMP_ADAPTER pAd,
1694 IN MLME_QUEUE_ELEM *Elem)
1696 USHORT Status;
1697 DBGPRINT(RT_DEBUG_TRACE, ("InvalidStateWhenJoin(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState));
1698 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1699 Status = MLME_STATE_MACHINE_REJECT;
1700 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status);
1704 ==========================================================================
1705 Description:
1706 ==========================================================================
1708 VOID InvalidStateWhenStart(
1709 IN PRTMP_ADAPTER pAd,
1710 IN MLME_QUEUE_ELEM *Elem)
1712 USHORT Status;
1713 DBGPRINT(RT_DEBUG_TRACE, ("InvalidStateWhenStart(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState));
1714 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1715 Status = MLME_STATE_MACHINE_REJECT;
1716 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status);
1720 ==========================================================================
1721 Description:
1723 IRQL = DISPATCH_LEVEL
1725 ==========================================================================
1727 VOID EnqueuePsPoll(
1728 IN PRTMP_ADAPTER pAd)
1730 if (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeLegacy_PSP)
1731 pAd->PsPollFrame.FC.PwrMgmt = PWR_SAVE;
1732 MiniportMMRequest(pAd, 0, (PUCHAR)&pAd->PsPollFrame, sizeof(PSPOLL_FRAME));
1737 ==========================================================================
1738 Description:
1739 ==========================================================================
1741 VOID EnqueueProbeRequest(
1742 IN PRTMP_ADAPTER pAd)
1744 NDIS_STATUS NState;
1745 PUCHAR pOutBuffer;
1746 ULONG FrameLen = 0;
1747 HEADER_802_11 Hdr80211;
1749 DBGPRINT(RT_DEBUG_TRACE, ("force out a ProbeRequest ...\n"));
1751 NState = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
1752 if (NState == NDIS_STATUS_SUCCESS)
1754 MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR);
1756 // this ProbeRequest explicitly specify SSID to reduce unwanted ProbeResponse
1757 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1758 sizeof(HEADER_802_11), &Hdr80211,
1759 1, &SsidIe,
1760 1, &pAd->CommonCfg.SsidLen,
1761 pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid,
1762 1, &SupRateIe,
1763 1, &pAd->StaActive.SupRateLen,
1764 pAd->StaActive.SupRateLen, pAd->StaActive.SupRate,
1765 END_OF_ARGS);
1766 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
1767 MlmeFreeMemory(pAd, pOutBuffer);
1772 BOOLEAN ScanRunning(
1773 IN PRTMP_ADAPTER pAd)
1775 return (pAd->Mlme.SyncMachine.CurrState == SCAN_LISTEN) ? TRUE : FALSE;