]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/rt2860/common/spectrum.c
Staging: rt28x0: remove typedefs (part one)
[net-next-2.6.git] / drivers / staging / rt2860 / common / spectrum.c
CommitLineData
91980990
GKH
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
91980990
GKH
27 Module Name:
28 action.c
29
30 Abstract:
31 Handle association related requests either from WSTA or from local MLME
32
33 Revision History:
34 Who When What
35 --------- ---------- ----------------------------------------------
36 Fonchi Wu 2008 created for 802.11h
37 */
38
39#include "../rt_config.h"
40#include "action.h"
41
ca97b838 42/* The regulatory information in the USA (US) */
96b3c83d 43DOT11_REGULATORY_INFORMATION USARegulatoryInfo[] = {
ca97b838 44/* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */
96b3c83d
BZ
45 {0, {0, 0, {0}
46 }
47 }
ec278fa2 48 , /* Invlid entry */
96b3c83d
BZ
49 {1, {4, 16, {36, 40, 44, 48}
50 }
51 }
52 ,
53 {2, {4, 23, {52, 56, 60, 64}
54 }
55 }
56 ,
57 {3, {4, 29, {149, 153, 157, 161}
58 }
59 }
60 ,
61 {4, {11, 23, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}
62 }
63 }
64 ,
65 {5, {5, 30, {149, 153, 157, 161, 165}
66 }
67 }
68 ,
69 {6, {10, 14, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
70 }
71 }
72 ,
73 {7, {10, 27, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
74 }
75 }
76 ,
77 {8, {5, 17, {11, 13, 15, 17, 19}
78 }
79 }
80 ,
81 {9, {5, 30, {11, 13, 15, 17, 19}
82 }
83 }
84 ,
85 {10, {2, 20, {21, 25}
86 }
87 }
88 ,
89 {11, {2, 33, {21, 25}
90 }
91 }
92 ,
93 {12, {11, 30, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
94 }
95 }
ca97b838 96};
ca97b838 97
96b3c83d 98#define USA_REGULATORY_INFO_SIZE (sizeof(USARegulatoryInfo) / sizeof(DOT11_REGULATORY_INFORMATION))
ca97b838
BZ
99
100/* The regulatory information in Europe */
96b3c83d 101DOT11_REGULATORY_INFORMATION EuropeRegulatoryInfo[] = {
ca97b838 102/* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */
96b3c83d
BZ
103 {0, {0, 0, {0}
104 }
105 }
ec278fa2 106 , /* Invalid entry */
96b3c83d
BZ
107 {1, {4, 20, {36, 40, 44, 48}
108 }
109 }
110 ,
111 {2, {4, 20, {52, 56, 60, 64}
112 }
113 }
114 ,
115 {3, {11, 30, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}
116 }
117 }
118 ,
119 {4, {13, 20, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}
120 }
121 }
ca97b838 122};
ca97b838 123
96b3c83d 124#define EU_REGULATORY_INFO_SIZE (sizeof(EuropeRegulatoryInfo) / sizeof(DOT11_REGULATORY_INFORMATION))
ca97b838
BZ
125
126/* The regulatory information in Japan */
96b3c83d 127DOT11_REGULATORY_INFORMATION JapanRegulatoryInfo[] = {
ca97b838 128/* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */
96b3c83d
BZ
129 {0, {0, 0, {0}
130 }
131 }
ec278fa2 132 , /* Invalid entry */
96b3c83d
BZ
133 {1, {4, 22, {34, 38, 42, 46}
134 }
135 }
136 ,
137 {2, {3, 24, {8, 12, 16}
138 }
139 }
140 ,
141 {3, {3, 24, {8, 12, 16}
142 }
143 }
144 ,
145 {4, {3, 24, {8, 12, 16}
146 }
147 }
148 ,
149 {5, {3, 24, {8, 12, 16}
150 }
151 }
152 ,
153 {6, {3, 22, {8, 12, 16}
154 }
155 }
156 ,
157 {7, {4, 24, {184, 188, 192, 196}
158 }
159 }
160 ,
161 {8, {4, 24, {184, 188, 192, 196}
162 }
163 }
164 ,
165 {9, {4, 24, {184, 188, 192, 196}
166 }
167 }
168 ,
169 {10, {4, 24, {184, 188, 192, 196}
170 }
171 }
172 ,
173 {11, {4, 22, {184, 188, 192, 196}
174 }
175 }
176 ,
177 {12, {4, 24, {7, 8, 9, 11}
178 }
179 }
180 ,
181 {13, {4, 24, {7, 8, 9, 11}
182 }
183 }
184 ,
185 {14, {4, 24, {7, 8, 9, 11}
186 }
187 }
188 ,
189 {15, {4, 24, {7, 8, 9, 11}
190 }
191 }
192 ,
193 {16, {6, 24, {183, 184, 185, 187, 188, 189}
194 }
195 }
196 ,
197 {17, {6, 24, {183, 184, 185, 187, 188, 189}
198 }
199 }
200 ,
201 {18, {6, 24, {183, 184, 185, 187, 188, 189}
202 }
203 }
204 ,
205 {19, {6, 24, {183, 184, 185, 187, 188, 189}
206 }
207 }
208 ,
209 {20, {6, 17, {183, 184, 185, 187, 188, 189}
210 }
211 }
212 ,
213 {21, {6, 24, {6, 7, 8, 9, 10, 11}
214 }
215 }
216 ,
217 {22, {6, 24, {6, 7, 8, 9, 10, 11}
218 }
219 }
220 ,
221 {23, {6, 24, {6, 7, 8, 9, 10, 11}
222 }
223 }
224 ,
225 {24, {6, 24, {6, 7, 8, 9, 10, 11}
226 }
227 }
228 ,
229 {25, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}
230 }
231 }
232 ,
233 {26, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}
234 }
235 }
236 ,
237 {27, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}
238 }
239 }
240 ,
241 {28, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}
242 }
243 }
244 ,
245 {29, {8, 17, {182, 183, 184, 185, 186, 187, 188, 189}
246 }
247 }
248 ,
249 {30, {13, 23, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}
250 }
251 }
252 ,
253 {31, {1, 23, {14}
254 }
255 }
256 ,
257 {32, {4, 22, {52, 56, 60, 64}
258 }
259 }
ca97b838 260};
ca97b838 261
96b3c83d 262#define JP_REGULATORY_INFO_SIZE (sizeof(JapanRegulatoryInfo) / sizeof(DOT11_REGULATORY_INFORMATION))
ca97b838 263
51126deb 264char RTMP_GetTxPwr(IN PRTMP_ADAPTER pAd, IN HTTRANSMIT_SETTING HTTxMode)
ca97b838 265{
96b3c83d 266 typedef struct __TX_PWR_CFG {
51126deb
BZ
267 u8 Mode;
268 u8 MCS;
269 u16 req;
270 u8 shift;
271 u32 BitMask;
96b3c83d 272 } TX_PWR_CFG;
ca97b838 273
51126deb
BZ
274 u32 Value;
275 int Idx;
276 u8 PhyMode;
277 char CurTxPwr;
278 u8 TxPwrRef = 0;
279 char DaltaPwr;
280 unsigned long TxPwr[5];
ca97b838 281
ca97b838
BZ
282 TX_PWR_CFG TxPwrCfg[] = {
283 {MODE_CCK, 0, 0, 4, 0x000000f0},
284 {MODE_CCK, 1, 0, 0, 0x0000000f},
285 {MODE_CCK, 2, 0, 12, 0x0000f000},
286 {MODE_CCK, 3, 0, 8, 0x00000f00},
287
288 {MODE_OFDM, 0, 0, 20, 0x00f00000},
289 {MODE_OFDM, 1, 0, 16, 0x000f0000},
290 {MODE_OFDM, 2, 0, 28, 0xf0000000},
291 {MODE_OFDM, 3, 0, 24, 0x0f000000},
292 {MODE_OFDM, 4, 1, 4, 0x000000f0},
293 {MODE_OFDM, 5, 1, 0, 0x0000000f},
294 {MODE_OFDM, 6, 1, 12, 0x0000f000},
295 {MODE_OFDM, 7, 1, 8, 0x00000f00}
96b3c83d 296 , {MODE_HTMIX, 0, 1, 20, 0x00f00000},
ca97b838
BZ
297 {MODE_HTMIX, 1, 1, 16, 0x000f0000},
298 {MODE_HTMIX, 2, 1, 28, 0xf0000000},
299 {MODE_HTMIX, 3, 1, 24, 0x0f000000},
300 {MODE_HTMIX, 4, 2, 4, 0x000000f0},
301 {MODE_HTMIX, 5, 2, 0, 0x0000000f},
302 {MODE_HTMIX, 6, 2, 12, 0x0000f000},
303 {MODE_HTMIX, 7, 2, 8, 0x00000f00},
304 {MODE_HTMIX, 8, 2, 20, 0x00f00000},
305 {MODE_HTMIX, 9, 2, 16, 0x000f0000},
306 {MODE_HTMIX, 10, 2, 28, 0xf0000000},
307 {MODE_HTMIX, 11, 2, 24, 0x0f000000},
308 {MODE_HTMIX, 12, 3, 4, 0x000000f0},
309 {MODE_HTMIX, 13, 3, 0, 0x0000000f},
310 {MODE_HTMIX, 14, 3, 12, 0x0000f000},
311 {MODE_HTMIX, 15, 3, 8, 0x00000f00}
312 };
313#define MAX_TXPWR_TAB_SIZE (sizeof(TxPwrCfg) / sizeof(TX_PWR_CFG))
314
315 CurTxPwr = 19;
316
317 /* check Tx Power setting from UI. */
96b3c83d
BZ
318 if (pAd->CommonCfg.TxPowerPercentage > 90) ;
319 else if (pAd->CommonCfg.TxPowerPercentage > 60) /* reduce Pwr for 1 dB. */
ca97b838 320 CurTxPwr -= 1;
96b3c83d 321 else if (pAd->CommonCfg.TxPowerPercentage > 30) /* reduce Pwr for 3 dB. */
ca97b838 322 CurTxPwr -= 3;
96b3c83d 323 else if (pAd->CommonCfg.TxPowerPercentage > 15) /* reduce Pwr for 6 dB. */
ca97b838 324 CurTxPwr -= 6;
96b3c83d 325 else if (pAd->CommonCfg.TxPowerPercentage > 9) /* reduce Pwr for 9 dB. */
ca97b838 326 CurTxPwr -= 9;
96b3c83d 327 else /* reduce Pwr for 12 dB. */
ca97b838
BZ
328 CurTxPwr -= 12;
329
96b3c83d
BZ
330 if (pAd->CommonCfg.BBPCurrentBW == BW_40) {
331 if (pAd->CommonCfg.CentralChannel > 14) {
ca97b838
BZ
332 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
333 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
334 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
335 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
336 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
96b3c83d 337 } else {
ca97b838
BZ
338 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
339 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
340 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
341 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
342 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
343 }
96b3c83d
BZ
344 } else {
345 if (pAd->CommonCfg.Channel > 14) {
ca97b838
BZ
346 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
347 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
348 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
349 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
350 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
96b3c83d 351 } else {
ca97b838
BZ
352 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
353 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
354 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
355 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
356 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
357 }
358 }
359
96b3c83d
BZ
360 switch (HTTxMode.field.MODE) {
361 case MODE_CCK:
362 case MODE_OFDM:
363 Value = TxPwr[1];
364 TxPwrRef = (Value & 0x00000f00) >> 8;
ca97b838 365
96b3c83d 366 break;
ca97b838 367
96b3c83d
BZ
368 case MODE_HTMIX:
369 case MODE_HTGREENFIELD:
370 if (pAd->CommonCfg.TxStream == 1) {
371 Value = TxPwr[2];
372 TxPwrRef = (Value & 0x00000f00) >> 8;
373 } else if (pAd->CommonCfg.TxStream == 2) {
374 Value = TxPwr[3];
375 TxPwrRef = (Value & 0x00000f00) >> 8;
376 }
377 break;
ca97b838
BZ
378 }
379
96b3c83d
BZ
380 PhyMode = (HTTxMode.field.MODE == MODE_HTGREENFIELD)
381 ? MODE_HTMIX : HTTxMode.field.MODE;
ca97b838 382
96b3c83d 383 for (Idx = 0; Idx < MAX_TXPWR_TAB_SIZE; Idx++) {
ca97b838 384 if ((TxPwrCfg[Idx].Mode == PhyMode)
96b3c83d 385 && (TxPwrCfg[Idx].MCS == HTTxMode.field.MCS)) {
ca97b838 386 Value = TxPwr[TxPwrCfg[Idx].req];
96b3c83d 387 DaltaPwr =
51126deb 388 TxPwrRef - (char)((Value & TxPwrCfg[Idx].BitMask)
96b3c83d 389 >> TxPwrCfg[Idx].shift);
ca97b838
BZ
390 CurTxPwr -= DaltaPwr;
391 break;
392 }
393 }
394
395 return CurTxPwr;
396}
397
51126deb 398void MeasureReqTabInit(IN PRTMP_ADAPTER pAd)
91980990
GKH
399{
400 NdisAllocateSpinLock(&pAd->CommonCfg.MeasureReqTabLock);
401
96b3c83d
BZ
402 pAd->CommonCfg.pMeasureReqTab =
403 kmalloc(sizeof(MEASURE_REQ_TAB), GFP_ATOMIC);
91980990 404 if (pAd->CommonCfg.pMeasureReqTab)
96b3c83d
BZ
405 NdisZeroMemory(pAd->CommonCfg.pMeasureReqTab,
406 sizeof(MEASURE_REQ_TAB));
91980990 407 else
96b3c83d
BZ
408 DBGPRINT(RT_DEBUG_ERROR,
409 ("%s Fail to alloc memory for pAd->CommonCfg.pMeasureReqTab.\n",
410 __func__));
91980990
GKH
411
412 return;
413}
414
51126deb 415void MeasureReqTabExit(IN PRTMP_ADAPTER pAd)
91980990 416{
ca97b838 417 NdisFreeSpinLock(&pAd->CommonCfg.MeasureReqTabLock);
91980990
GKH
418
419 if (pAd->CommonCfg.pMeasureReqTab)
420 kfree(pAd->CommonCfg.pMeasureReqTab);
421 pAd->CommonCfg.pMeasureReqTab = NULL;
422
423 return;
424}
425
51126deb 426PMEASURE_REQ_ENTRY MeasureReqLookUp(IN PRTMP_ADAPTER pAd, u8 DialogToken)
91980990 427{
51126deb 428 u32 HashIdx;
91980990
GKH
429 PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
430 PMEASURE_REQ_ENTRY pEntry = NULL;
431 PMEASURE_REQ_ENTRY pPrevEntry = NULL;
432
96b3c83d
BZ
433 if (pTab == NULL) {
434 DBGPRINT(RT_DEBUG_ERROR,
435 ("%s: pMeasureReqTab doesn't exist.\n", __func__));
91980990
GKH
436 return NULL;
437 }
438
439 RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
440
441 HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken);
442 pEntry = pTab->Hash[HashIdx];
443
96b3c83d 444 while (pEntry) {
91980990
GKH
445 if (pEntry->DialogToken == DialogToken)
446 break;
96b3c83d 447 else {
91980990
GKH
448 pPrevEntry = pEntry;
449 pEntry = pEntry->pNext;
450 }
451 }
452
453 RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
454
455 return pEntry;
456}
457
51126deb 458PMEASURE_REQ_ENTRY MeasureReqInsert(IN PRTMP_ADAPTER pAd, u8 DialogToken)
91980990 459{
51126deb
BZ
460 int i;
461 unsigned long HashIdx;
91980990
GKH
462 PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
463 PMEASURE_REQ_ENTRY pEntry = NULL, pCurrEntry;
51126deb 464 unsigned long Now;
91980990 465
96b3c83d
BZ
466 if (pTab == NULL) {
467 DBGPRINT(RT_DEBUG_ERROR,
468 ("%s: pMeasureReqTab doesn't exist.\n", __func__));
91980990
GKH
469 return NULL;
470 }
471
472 pEntry = MeasureReqLookUp(pAd, DialogToken);
96b3c83d 473 if (pEntry == NULL) {
91980990 474 RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
96b3c83d 475 for (i = 0; i < MAX_MEASURE_REQ_TAB_SIZE; i++) {
91980990
GKH
476 NdisGetSystemUpTime(&Now);
477 pEntry = &pTab->Content[i];
478
479 if ((pEntry->Valid == TRUE)
96b3c83d
BZ
480 && RTMP_TIME_AFTER((unsigned long)Now,
481 (unsigned long)(pEntry->
482 lastTime +
483 MQ_REQ_AGE_OUT)))
91980990
GKH
484 {
485 PMEASURE_REQ_ENTRY pPrevEntry = NULL;
51126deb 486 unsigned long HashIdx =
96b3c83d
BZ
487 MQ_DIALOGTOKEN_HASH_INDEX(pEntry->
488 DialogToken);
489 PMEASURE_REQ_ENTRY pProbeEntry =
490 pTab->Hash[HashIdx];
91980990 491
ec278fa2 492 /* update Hash list */
96b3c83d
BZ
493 do {
494 if (pProbeEntry == pEntry) {
495 if (pPrevEntry == NULL) {
496 pTab->Hash[HashIdx] =
497 pEntry->pNext;
498 } else {
499 pPrevEntry->pNext =
500 pEntry->pNext;
91980990
GKH
501 }
502 break;
503 }
504
505 pPrevEntry = pProbeEntry;
506 pProbeEntry = pProbeEntry->pNext;
507 } while (pProbeEntry);
508
96b3c83d
BZ
509 NdisZeroMemory(pEntry,
510 sizeof(MEASURE_REQ_ENTRY));
91980990
GKH
511 pTab->Size--;
512
513 break;
514 }
515
516 if (pEntry->Valid == FALSE)
517 break;
518 }
519
96b3c83d 520 if (i < MAX_MEASURE_REQ_TAB_SIZE) {
91980990
GKH
521 NdisGetSystemUpTime(&Now);
522 pEntry->lastTime = Now;
523 pEntry->Valid = TRUE;
524 pEntry->DialogToken = DialogToken;
525 pTab->Size++;
96b3c83d 526 } else {
91980990 527 pEntry = NULL;
96b3c83d
BZ
528 DBGPRINT(RT_DEBUG_ERROR,
529 ("%s: pMeasureReqTab tab full.\n", __func__));
91980990
GKH
530 }
531
ec278fa2 532 /* add this Neighbor entry into HASH table */
96b3c83d 533 if (pEntry) {
91980990 534 HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken);
96b3c83d 535 if (pTab->Hash[HashIdx] == NULL) {
91980990 536 pTab->Hash[HashIdx] = pEntry;
96b3c83d 537 } else {
91980990
GKH
538 pCurrEntry = pTab->Hash[HashIdx];
539 while (pCurrEntry->pNext != NULL)
540 pCurrEntry = pCurrEntry->pNext;
541 pCurrEntry->pNext = pEntry;
542 }
543 }
544
545 RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
546 }
547
548 return pEntry;
549}
550
51126deb 551void MeasureReqDelete(IN PRTMP_ADAPTER pAd, u8 DialogToken)
91980990
GKH
552{
553 PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
554 PMEASURE_REQ_ENTRY pEntry = NULL;
555
96b3c83d
BZ
556 if (pTab == NULL) {
557 DBGPRINT(RT_DEBUG_ERROR,
558 ("%s: pMeasureReqTab doesn't exist.\n", __func__));
91980990
GKH
559 return;
560 }
ec278fa2 561 /* if empty, return */
96b3c83d 562 if (pTab->Size == 0) {
91980990
GKH
563 DBGPRINT(RT_DEBUG_ERROR, ("pMeasureReqTab empty.\n"));
564 return;
565 }
566
567 pEntry = MeasureReqLookUp(pAd, DialogToken);
96b3c83d 568 if (pEntry != NULL) {
91980990 569 PMEASURE_REQ_ENTRY pPrevEntry = NULL;
51126deb 570 unsigned long HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
91980990
GKH
571 PMEASURE_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
572
573 RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
ec278fa2 574 /* update Hash list */
96b3c83d
BZ
575 do {
576 if (pProbeEntry == pEntry) {
577 if (pPrevEntry == NULL) {
91980990 578 pTab->Hash[HashIdx] = pEntry->pNext;
96b3c83d 579 } else {
91980990
GKH
580 pPrevEntry->pNext = pEntry->pNext;
581 }
582 break;
583 }
584
585 pPrevEntry = pProbeEntry;
586 pProbeEntry = pProbeEntry->pNext;
587 } while (pProbeEntry);
588
589 NdisZeroMemory(pEntry, sizeof(MEASURE_REQ_ENTRY));
590 pTab->Size--;
591
592 RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
593 }
594
595 return;
596}
597
51126deb 598void TpcReqTabInit(IN PRTMP_ADAPTER pAd)
91980990
GKH
599{
600 NdisAllocateSpinLock(&pAd->CommonCfg.TpcReqTabLock);
601
602 pAd->CommonCfg.pTpcReqTab = kmalloc(sizeof(TPC_REQ_TAB), GFP_ATOMIC);
603 if (pAd->CommonCfg.pTpcReqTab)
604 NdisZeroMemory(pAd->CommonCfg.pTpcReqTab, sizeof(TPC_REQ_TAB));
605 else
96b3c83d
BZ
606 DBGPRINT(RT_DEBUG_ERROR,
607 ("%s Fail to alloc memory for pAd->CommonCfg.pTpcReqTab.\n",
608 __func__));
91980990
GKH
609
610 return;
611}
612
51126deb 613void TpcReqTabExit(IN PRTMP_ADAPTER pAd)
91980990 614{
ca97b838 615 NdisFreeSpinLock(&pAd->CommonCfg.TpcReqTabLock);
91980990
GKH
616
617 if (pAd->CommonCfg.pTpcReqTab)
618 kfree(pAd->CommonCfg.pTpcReqTab);
619 pAd->CommonCfg.pTpcReqTab = NULL;
620
621 return;
622}
623
51126deb 624static PTPC_REQ_ENTRY TpcReqLookUp(IN PRTMP_ADAPTER pAd, u8 DialogToken)
91980990 625{
51126deb 626 u32 HashIdx;
91980990
GKH
627 PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
628 PTPC_REQ_ENTRY pEntry = NULL;
629 PTPC_REQ_ENTRY pPrevEntry = NULL;
630
96b3c83d
BZ
631 if (pTab == NULL) {
632 DBGPRINT(RT_DEBUG_ERROR,
633 ("%s: pTpcReqTab doesn't exist.\n", __func__));
91980990
GKH
634 return NULL;
635 }
636
637 RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
638
639 HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken);
640 pEntry = pTab->Hash[HashIdx];
641
96b3c83d 642 while (pEntry) {
91980990
GKH
643 if (pEntry->DialogToken == DialogToken)
644 break;
96b3c83d 645 else {
91980990
GKH
646 pPrevEntry = pEntry;
647 pEntry = pEntry->pNext;
648 }
649 }
650
651 RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
652
653 return pEntry;
654}
655
51126deb 656static PTPC_REQ_ENTRY TpcReqInsert(IN PRTMP_ADAPTER pAd, u8 DialogToken)
91980990 657{
51126deb
BZ
658 int i;
659 unsigned long HashIdx;
91980990
GKH
660 PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
661 PTPC_REQ_ENTRY pEntry = NULL, pCurrEntry;
51126deb 662 unsigned long Now;
91980990 663
96b3c83d
BZ
664 if (pTab == NULL) {
665 DBGPRINT(RT_DEBUG_ERROR,
666 ("%s: pTpcReqTab doesn't exist.\n", __func__));
91980990
GKH
667 return NULL;
668 }
669
670 pEntry = TpcReqLookUp(pAd, DialogToken);
96b3c83d 671 if (pEntry == NULL) {
91980990 672 RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
96b3c83d 673 for (i = 0; i < MAX_TPC_REQ_TAB_SIZE; i++) {
91980990
GKH
674 NdisGetSystemUpTime(&Now);
675 pEntry = &pTab->Content[i];
676
677 if ((pEntry->Valid == TRUE)
96b3c83d
BZ
678 && RTMP_TIME_AFTER((unsigned long)Now,
679 (unsigned long)(pEntry->
680 lastTime +
681 TPC_REQ_AGE_OUT)))
91980990
GKH
682 {
683 PTPC_REQ_ENTRY pPrevEntry = NULL;
51126deb 684 unsigned long HashIdx =
96b3c83d
BZ
685 TPC_DIALOGTOKEN_HASH_INDEX(pEntry->
686 DialogToken);
687 PTPC_REQ_ENTRY pProbeEntry =
688 pTab->Hash[HashIdx];
91980990 689
ec278fa2 690 /* update Hash list */
96b3c83d
BZ
691 do {
692 if (pProbeEntry == pEntry) {
693 if (pPrevEntry == NULL) {
694 pTab->Hash[HashIdx] =
695 pEntry->pNext;
696 } else {
697 pPrevEntry->pNext =
698 pEntry->pNext;
91980990
GKH
699 }
700 break;
701 }
702
703 pPrevEntry = pProbeEntry;
704 pProbeEntry = pProbeEntry->pNext;
705 } while (pProbeEntry);
706
707 NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY));
708 pTab->Size--;
709
710 break;
711 }
712
713 if (pEntry->Valid == FALSE)
714 break;
715 }
716
96b3c83d 717 if (i < MAX_TPC_REQ_TAB_SIZE) {
91980990
GKH
718 NdisGetSystemUpTime(&Now);
719 pEntry->lastTime = Now;
720 pEntry->Valid = TRUE;
721 pEntry->DialogToken = DialogToken;
722 pTab->Size++;
96b3c83d 723 } else {
91980990 724 pEntry = NULL;
96b3c83d
BZ
725 DBGPRINT(RT_DEBUG_ERROR,
726 ("%s: pTpcReqTab tab full.\n", __func__));
91980990
GKH
727 }
728
ec278fa2 729 /* add this Neighbor entry into HASH table */
96b3c83d 730 if (pEntry) {
91980990 731 HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken);
96b3c83d 732 if (pTab->Hash[HashIdx] == NULL) {
91980990 733 pTab->Hash[HashIdx] = pEntry;
96b3c83d 734 } else {
91980990
GKH
735 pCurrEntry = pTab->Hash[HashIdx];
736 while (pCurrEntry->pNext != NULL)
737 pCurrEntry = pCurrEntry->pNext;
738 pCurrEntry->pNext = pEntry;
739 }
740 }
741
742 RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
743 }
744
745 return pEntry;
746}
747
51126deb 748static void TpcReqDelete(IN PRTMP_ADAPTER pAd, u8 DialogToken)
91980990
GKH
749{
750 PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
751 PTPC_REQ_ENTRY pEntry = NULL;
752
96b3c83d
BZ
753 if (pTab == NULL) {
754 DBGPRINT(RT_DEBUG_ERROR,
755 ("%s: pTpcReqTab doesn't exist.\n", __func__));
91980990
GKH
756 return;
757 }
ec278fa2 758 /* if empty, return */
96b3c83d 759 if (pTab->Size == 0) {
91980990
GKH
760 DBGPRINT(RT_DEBUG_ERROR, ("pTpcReqTab empty.\n"));
761 return;
762 }
763
764 pEntry = TpcReqLookUp(pAd, DialogToken);
96b3c83d 765 if (pEntry != NULL) {
91980990 766 PTPC_REQ_ENTRY pPrevEntry = NULL;
51126deb 767 unsigned long HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
91980990
GKH
768 PTPC_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
769
770 RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
ec278fa2 771 /* update Hash list */
96b3c83d
BZ
772 do {
773 if (pProbeEntry == pEntry) {
774 if (pPrevEntry == NULL) {
91980990 775 pTab->Hash[HashIdx] = pEntry->pNext;
96b3c83d 776 } else {
91980990
GKH
777 pPrevEntry->pNext = pEntry->pNext;
778 }
779 break;
780 }
781
782 pPrevEntry = pProbeEntry;
783 pProbeEntry = pProbeEntry->pNext;
784 } while (pProbeEntry);
785
786 NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY));
787 pTab->Size--;
788
789 RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
790 }
791
792 return;
793}
794
795/*
796 ==========================================================================
797 Description:
798 Get Current TimeS tamp.
799
800 Parametrs:
801
802 Return : Current Time Stamp.
803 ==========================================================================
804 */
51126deb 805static u64 GetCurrentTimeStamp(IN PRTMP_ADAPTER pAd)
91980990 806{
ec278fa2 807 /* get current time stamp. */
91980990
GKH
808 return 0;
809}
810
811/*
812 ==========================================================================
813 Description:
814 Get Current Transmit Power.
815
816 Parametrs:
817
818 Return : Current Time Stamp.
819 ==========================================================================
820 */
51126deb 821static u8 GetCurTxPwr(IN PRTMP_ADAPTER pAd, u8 Wcid)
91980990 822{
96b3c83d 823 return 16; /* 16 dBm */
91980990
GKH
824}
825
ca97b838
BZ
826/*
827 ==========================================================================
828 Description:
829 Get Current Transmit Power.
830
831 Parametrs:
832
833 Return : Current Time Stamp.
834 ==========================================================================
835 */
51126deb
BZ
836void InsertChannelRepIE(IN PRTMP_ADAPTER pAd,
837 u8 *pFrameBuf,
838 unsigned long *pFrameLen,
839 char *pCountry, u8 RegulatoryClass)
ca97b838 840{
51126deb
BZ
841 unsigned long TempLen;
842 u8 Len;
843 u8 IEId = IE_AP_CHANNEL_REPORT;
844 u8 *pChListPtr = NULL;
ca97b838
BZ
845
846 Len = 1;
96b3c83d
BZ
847 if (strncmp(pCountry, "US", 2) == 0) {
848 if (RegulatoryClass >= USA_REGULATORY_INFO_SIZE) {
849 DBGPRINT(RT_DEBUG_ERROR,
850 ("%s: USA Unknow Requlatory class (%d)\n",
851 __func__, RegulatoryClass));
ca97b838
BZ
852 return;
853 }
854
96b3c83d
BZ
855 Len +=
856 USARegulatoryInfo[RegulatoryClass].ChannelSet.
857 NumberOfChannels;
858 pChListPtr =
859 USARegulatoryInfo[RegulatoryClass].ChannelSet.ChannelList;
860 } else if (strncmp(pCountry, "JP", 2) == 0) {
861 if (RegulatoryClass >= JP_REGULATORY_INFO_SIZE) {
862 DBGPRINT(RT_DEBUG_ERROR,
863 ("%s: JP Unknow Requlatory class (%d)\n",
864 __func__, RegulatoryClass));
ca97b838
BZ
865 return;
866 }
867
96b3c83d
BZ
868 Len +=
869 JapanRegulatoryInfo[RegulatoryClass].ChannelSet.
870 NumberOfChannels;
871 pChListPtr =
872 JapanRegulatoryInfo[RegulatoryClass].ChannelSet.ChannelList;
873 } else {
ca97b838 874 DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow Country (%s)\n",
96b3c83d 875 __func__, pCountry));
ca97b838
BZ
876 return;
877 }
878
96b3c83d
BZ
879 MakeOutgoingFrame(pFrameBuf, &TempLen,
880 1, &IEId,
881 1, &Len,
882 1, &RegulatoryClass,
883 Len - 1, pChListPtr, END_OF_ARGS);
ca97b838
BZ
884
885 *pFrameLen = *pFrameLen + TempLen;
886
887 return;
888}
889
91980990
GKH
890/*
891 ==========================================================================
892 Description:
893 Insert Dialog Token into frame.
894
895 Parametrs:
896 1. frame buffer pointer.
897 2. frame length.
898 3. Dialog token.
899
900 Return : None.
901 ==========================================================================
902 */
51126deb
BZ
903void InsertDialogToken(IN PRTMP_ADAPTER pAd,
904 u8 *pFrameBuf,
905 unsigned long *pFrameLen, u8 DialogToken)
91980990 906{
51126deb 907 unsigned long TempLen;
96b3c83d 908 MakeOutgoingFrame(pFrameBuf, &TempLen, 1, &DialogToken, END_OF_ARGS);
91980990
GKH
909
910 *pFrameLen = *pFrameLen + TempLen;
911
912 return;
913}
914
915/*
916 ==========================================================================
917 Description:
918 Insert TPC Request IE into frame.
919
920 Parametrs:
921 1. frame buffer pointer.
922 2. frame length.
923
924 Return : None.
925 ==========================================================================
926 */
51126deb
BZ
927static void InsertTpcReqIE(IN PRTMP_ADAPTER pAd,
928 u8 *pFrameBuf, unsigned long *pFrameLen)
91980990 929{
51126deb
BZ
930 unsigned long TempLen;
931 unsigned long Len = 0;
932 u8 ElementID = IE_TPC_REQUEST;
91980990 933
96b3c83d
BZ
934 MakeOutgoingFrame(pFrameBuf, &TempLen,
935 1, &ElementID, 1, &Len, END_OF_ARGS);
91980990
GKH
936
937 *pFrameLen = *pFrameLen + TempLen;
938
939 return;
940}
941
942/*
943 ==========================================================================
944 Description:
945 Insert TPC Report IE into frame.
946
947 Parametrs:
948 1. frame buffer pointer.
949 2. frame length.
950 3. Transmit Power.
951 4. Link Margin.
952
953 Return : None.
954 ==========================================================================
955 */
51126deb
BZ
956void InsertTpcReportIE(IN PRTMP_ADAPTER pAd,
957 u8 *pFrameBuf,
958 unsigned long *pFrameLen,
959 u8 TxPwr, u8 LinkMargin)
91980990 960{
51126deb
BZ
961 unsigned long TempLen;
962 unsigned long Len = sizeof(TPC_REPORT_INFO);
963 u8 ElementID = IE_TPC_REPORT;
91980990
GKH
964 TPC_REPORT_INFO TpcReportIE;
965
966 TpcReportIE.TxPwr = TxPwr;
967 TpcReportIE.LinkMargin = LinkMargin;
968
96b3c83d
BZ
969 MakeOutgoingFrame(pFrameBuf, &TempLen,
970 1, &ElementID,
971 1, &Len, Len, &TpcReportIE, END_OF_ARGS);
91980990
GKH
972
973 *pFrameLen = *pFrameLen + TempLen;
974
91980990
GKH
975 return;
976}
977
978/*
979 ==========================================================================
980 Description:
981 Insert Channel Switch Announcement IE into frame.
982
983 Parametrs:
984 1. frame buffer pointer.
985 2. frame length.
986 3. channel switch announcement mode.
987 4. new selected channel.
988 5. channel switch announcement count.
989
990 Return : None.
991 ==========================================================================
992 */
51126deb
BZ
993static void InsertChSwAnnIE(IN PRTMP_ADAPTER pAd,
994 u8 *pFrameBuf,
995 unsigned long *pFrameLen,
996 u8 ChSwMode,
997 u8 NewChannel, u8 ChSwCnt)
91980990 998{
51126deb
BZ
999 unsigned long TempLen;
1000 unsigned long Len = sizeof(CH_SW_ANN_INFO);
1001 u8 ElementID = IE_CHANNEL_SWITCH_ANNOUNCEMENT;
91980990
GKH
1002 CH_SW_ANN_INFO ChSwAnnIE;
1003
1004 ChSwAnnIE.ChSwMode = ChSwMode;
1005 ChSwAnnIE.Channel = NewChannel;
1006 ChSwAnnIE.ChSwCnt = ChSwCnt;
1007
96b3c83d
BZ
1008 MakeOutgoingFrame(pFrameBuf, &TempLen,
1009 1, &ElementID, 1, &Len, Len, &ChSwAnnIE, END_OF_ARGS);
91980990
GKH
1010
1011 *pFrameLen = *pFrameLen + TempLen;
1012
91980990
GKH
1013 return;
1014}
1015
1016/*
1017 ==========================================================================
1018 Description:
1019 Insert Measure Request IE into frame.
1020
1021 Parametrs:
1022 1. frame buffer pointer.
1023 2. frame length.
1024 3. Measure Token.
1025 4. Measure Request Mode.
1026 5. Measure Request Type.
1027 6. Measure Channel.
1028 7. Measure Start time.
1029 8. Measure Duration.
1030
91980990
GKH
1031 Return : None.
1032 ==========================================================================
1033 */
51126deb
BZ
1034static void InsertMeasureReqIE(IN PRTMP_ADAPTER pAd,
1035 u8 *pFrameBuf,
1036 unsigned long *pFrameLen,
1037 u8 Len, IN PMEASURE_REQ_INFO pMeasureReqIE)
91980990 1038{
51126deb
BZ
1039 unsigned long TempLen;
1040 u8 ElementID = IE_MEASUREMENT_REQUEST;
91980990 1041
96b3c83d
BZ
1042 MakeOutgoingFrame(pFrameBuf, &TempLen,
1043 1, &ElementID,
1044 1, &Len,
1045 sizeof(MEASURE_REQ_INFO), pMeasureReqIE, END_OF_ARGS);
91980990
GKH
1046
1047 *pFrameLen = *pFrameLen + TempLen;
1048
1049 return;
1050}
1051
1052/*
1053 ==========================================================================
1054 Description:
1055 Insert Measure Report IE into frame.
1056
1057 Parametrs:
1058 1. frame buffer pointer.
1059 2. frame length.
1060 3. Measure Token.
1061 4. Measure Request Mode.
1062 5. Measure Request Type.
1063 6. Length of Report Infomation
1064 7. Pointer of Report Infomation Buffer.
1065
1066 Return : None.
1067 ==========================================================================
1068 */
51126deb
BZ
1069static void InsertMeasureReportIE(IN PRTMP_ADAPTER pAd,
1070 u8 *pFrameBuf,
1071 unsigned long *pFrameLen,
96b3c83d 1072 IN PMEASURE_REPORT_INFO pMeasureReportIE,
51126deb 1073 u8 ReportLnfoLen, u8 *pReportInfo)
91980990 1074{
51126deb
BZ
1075 unsigned long TempLen;
1076 unsigned long Len;
1077 u8 ElementID = IE_MEASUREMENT_REPORT;
91980990
GKH
1078
1079 Len = sizeof(MEASURE_REPORT_INFO) + ReportLnfoLen;
1080
96b3c83d
BZ
1081 MakeOutgoingFrame(pFrameBuf, &TempLen,
1082 1, &ElementID,
1083 1, &Len, Len, pMeasureReportIE, END_OF_ARGS);
91980990
GKH
1084
1085 *pFrameLen = *pFrameLen + TempLen;
1086
96b3c83d
BZ
1087 if ((ReportLnfoLen > 0) && (pReportInfo != NULL)) {
1088 MakeOutgoingFrame(pFrameBuf + *pFrameLen, &TempLen,
1089 ReportLnfoLen, pReportInfo, END_OF_ARGS);
91980990
GKH
1090
1091 *pFrameLen = *pFrameLen + TempLen;
1092 }
1093 return;
1094}
1095
1096/*
1097 ==========================================================================
1098 Description:
1099 Prepare Measurement request action frame and enqueue it into
1100 management queue waiting for transmition.
1101
1102 Parametrs:
1103 1. the destination mac address of the frame.
1104
1105 Return : None.
1106 ==========================================================================
1107 */
51126deb
BZ
1108void MakeMeasurementReqFrame(IN PRTMP_ADAPTER pAd,
1109 u8 *pOutBuffer,
1110 unsigned long *pFrameLen,
1111 u8 TotalLen,
1112 u8 Category,
1113 u8 Action,
1114 u8 MeasureToken,
1115 u8 MeasureReqMode,
1116 u8 MeasureReqType, u8 NumOfRepetitions)
91980990 1117{
51126deb 1118 unsigned long TempLen;
91980990 1119 MEASURE_REQ_INFO MeasureReqIE;
91980990 1120
96b3c83d
BZ
1121 InsertActField(pAd, (pOutBuffer + *pFrameLen), pFrameLen, Category,
1122 Action);
91980990 1123
ec278fa2 1124 /* fill Dialog Token */
96b3c83d
BZ
1125 InsertDialogToken(pAd, (pOutBuffer + *pFrameLen), pFrameLen,
1126 MeasureToken);
91980990 1127
ca97b838 1128 /* fill Number of repetitions. */
96b3c83d
BZ
1129 if (Category == CATEGORY_RM) {
1130 MakeOutgoingFrame((pOutBuffer + *pFrameLen), &TempLen,
1131 2, &NumOfRepetitions, END_OF_ARGS);
91980990 1132
ca97b838
BZ
1133 *pFrameLen += TempLen;
1134 }
ec278fa2 1135 /* prepare Measurement IE. */
91980990 1136 NdisZeroMemory(&MeasureReqIE, sizeof(MEASURE_REQ_INFO));
ca97b838 1137 MeasureReqIE.Token = MeasureToken;
91980990
GKH
1138 MeasureReqIE.ReqMode.word = MeasureReqMode;
1139 MeasureReqIE.ReqType = MeasureReqType;
96b3c83d
BZ
1140 InsertMeasureReqIE(pAd, (pOutBuffer + *pFrameLen), pFrameLen,
1141 TotalLen, &MeasureReqIE);
91980990
GKH
1142
1143 return;
1144}
1145
1146/*
1147 ==========================================================================
1148 Description:
1149 Prepare Measurement report action frame and enqueue it into
1150 management queue waiting for transmition.
1151
1152 Parametrs:
1153 1. the destination mac address of the frame.
1154
1155 Return : None.
1156 ==========================================================================
1157 */
51126deb
BZ
1158void EnqueueMeasurementRep(IN PRTMP_ADAPTER pAd,
1159 u8 *pDA,
1160 u8 DialogToken,
1161 u8 MeasureToken,
1162 u8 MeasureReqMode,
1163 u8 MeasureReqType,
1164 u8 ReportInfoLen, u8 *pReportInfo)
91980990 1165{
51126deb
BZ
1166 u8 *pOutBuffer = NULL;
1167 int NStatus;
1168 unsigned long FrameLen;
91980990
GKH
1169 HEADER_802_11 ActHdr;
1170 MEASURE_REPORT_INFO MeasureRepIE;
1171
ec278fa2 1172 /* build action frame header. */
91980990 1173 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
96b3c83d 1174 pAd->CurrentAddress);
91980990 1175
51126deb 1176 NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */
96b3c83d
BZ
1177 if (NStatus != NDIS_STATUS_SUCCESS) {
1178 DBGPRINT(RT_DEBUG_TRACE,
1179 ("%s() allocate memory failed \n", __func__));
91980990
GKH
1180 return;
1181 }
51126deb 1182 NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(HEADER_802_11));
91980990
GKH
1183 FrameLen = sizeof(HEADER_802_11);
1184
96b3c83d
BZ
1185 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen,
1186 CATEGORY_SPECTRUM, SPEC_MRP);
91980990 1187
ec278fa2 1188 /* fill Dialog Token */
91980990
GKH
1189 InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
1190
ec278fa2 1191 /* prepare Measurement IE. */
91980990
GKH
1192 NdisZeroMemory(&MeasureRepIE, sizeof(MEASURE_REPORT_INFO));
1193 MeasureRepIE.Token = MeasureToken;
ca97b838 1194 MeasureRepIE.ReportMode = MeasureReqMode;
91980990 1195 MeasureRepIE.ReportType = MeasureReqType;
96b3c83d
BZ
1196 InsertMeasureReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen,
1197 &MeasureRepIE, ReportInfoLen, pReportInfo);
91980990
GKH
1198
1199 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1200 MlmeFreeMemory(pAd, pOutBuffer);
1201
1202 return;
1203}
1204
1205/*
1206 ==========================================================================
1207 Description:
1208 Prepare TPC Request action frame and enqueue it into
1209 management queue waiting for transmition.
1210
1211 Parametrs:
1212 1. the destination mac address of the frame.
1213
1214 Return : None.
1215 ==========================================================================
1216 */
51126deb 1217void EnqueueTPCReq(IN PRTMP_ADAPTER pAd, u8 *pDA, u8 DialogToken)
91980990 1218{
51126deb
BZ
1219 u8 *pOutBuffer = NULL;
1220 int NStatus;
1221 unsigned long FrameLen;
91980990
GKH
1222
1223 HEADER_802_11 ActHdr;
1224
ec278fa2 1225 /* build action frame header. */
91980990 1226 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
96b3c83d 1227 pAd->CurrentAddress);
91980990 1228
51126deb 1229 NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */
96b3c83d
BZ
1230 if (NStatus != NDIS_STATUS_SUCCESS) {
1231 DBGPRINT(RT_DEBUG_TRACE,
1232 ("%s() allocate memory failed \n", __func__));
91980990
GKH
1233 return;
1234 }
51126deb 1235 NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(HEADER_802_11));
91980990
GKH
1236 FrameLen = sizeof(HEADER_802_11);
1237
96b3c83d
BZ
1238 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen,
1239 CATEGORY_SPECTRUM, SPEC_TPCRQ);
91980990 1240
ec278fa2 1241 /* fill Dialog Token */
91980990
GKH
1242 InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
1243
ec278fa2 1244 /* Insert TPC Request IE. */
91980990
GKH
1245 InsertTpcReqIE(pAd, (pOutBuffer + FrameLen), &FrameLen);
1246
1247 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1248 MlmeFreeMemory(pAd, pOutBuffer);
1249
1250 return;
1251}
1252
1253/*
1254 ==========================================================================
1255 Description:
1256 Prepare TPC Report action frame and enqueue it into
1257 management queue waiting for transmition.
1258
1259 Parametrs:
1260 1. the destination mac address of the frame.
1261
1262 Return : None.
1263 ==========================================================================
1264 */
51126deb
BZ
1265void EnqueueTPCRep(IN PRTMP_ADAPTER pAd,
1266 u8 *pDA,
1267 u8 DialogToken, u8 TxPwr, u8 LinkMargin)
91980990 1268{
51126deb
BZ
1269 u8 *pOutBuffer = NULL;
1270 int NStatus;
1271 unsigned long FrameLen;
91980990
GKH
1272
1273 HEADER_802_11 ActHdr;
1274
ec278fa2 1275 /* build action frame header. */
91980990 1276 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
96b3c83d 1277 pAd->CurrentAddress);
91980990 1278
51126deb 1279 NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */
96b3c83d
BZ
1280 if (NStatus != NDIS_STATUS_SUCCESS) {
1281 DBGPRINT(RT_DEBUG_TRACE,
1282 ("%s() allocate memory failed \n", __func__));
91980990
GKH
1283 return;
1284 }
51126deb 1285 NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(HEADER_802_11));
91980990
GKH
1286 FrameLen = sizeof(HEADER_802_11);
1287
96b3c83d
BZ
1288 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen,
1289 CATEGORY_SPECTRUM, SPEC_TPCRP);
91980990 1290
ec278fa2 1291 /* fill Dialog Token */
91980990
GKH
1292 InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
1293
ec278fa2 1294 /* Insert TPC Request IE. */
96b3c83d
BZ
1295 InsertTpcReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, TxPwr,
1296 LinkMargin);
91980990
GKH
1297
1298 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1299 MlmeFreeMemory(pAd, pOutBuffer);
1300
1301 return;
1302}
1303
1304/*
1305 ==========================================================================
1306 Description:
1307 Prepare Channel Switch Announcement action frame and enqueue it into
1308 management queue waiting for transmition.
1309
1310 Parametrs:
1311 1. the destination mac address of the frame.
1312 2. Channel switch announcement mode.
1313 2. a New selected channel.
1314
1315 Return : None.
1316 ==========================================================================
1317 */
51126deb
BZ
1318void EnqueueChSwAnn(IN PRTMP_ADAPTER pAd,
1319 u8 *pDA, u8 ChSwMode, u8 NewCh)
91980990 1320{
51126deb
BZ
1321 u8 *pOutBuffer = NULL;
1322 int NStatus;
1323 unsigned long FrameLen;
91980990
GKH
1324
1325 HEADER_802_11 ActHdr;
1326
ec278fa2 1327 /* build action frame header. */
91980990 1328 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
96b3c83d 1329 pAd->CurrentAddress);
91980990 1330
51126deb 1331 NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */
96b3c83d
BZ
1332 if (NStatus != NDIS_STATUS_SUCCESS) {
1333 DBGPRINT(RT_DEBUG_TRACE,
1334 ("%s() allocate memory failed \n", __func__));
91980990
GKH
1335 return;
1336 }
51126deb 1337 NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(HEADER_802_11));
91980990
GKH
1338 FrameLen = sizeof(HEADER_802_11);
1339
96b3c83d
BZ
1340 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen,
1341 CATEGORY_SPECTRUM, SPEC_CHANNEL_SWITCH);
91980990 1342
96b3c83d
BZ
1343 InsertChSwAnnIE(pAd, (pOutBuffer + FrameLen), &FrameLen, ChSwMode,
1344 NewCh, 0);
91980990
GKH
1345
1346 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1347 MlmeFreeMemory(pAd, pOutBuffer);
1348
1349 return;
1350}
1351
51126deb 1352static BOOLEAN DfsRequirementCheck(IN PRTMP_ADAPTER pAd, u8 Channel)
91980990
GKH
1353{
1354 BOOLEAN Result = FALSE;
51126deb 1355 int i;
91980990 1356
96b3c83d 1357 do {
ec278fa2
BZ
1358 /* check DFS procedure is running. */
1359 /* make sure DFS procedure won't start twice. */
96b3c83d 1360 if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE) {
91980990
GKH
1361 Result = FALSE;
1362 break;
1363 }
ec278fa2 1364 /* check the new channel carried from Channel Switch Announcemnet is valid. */
96b3c83d 1365 for (i = 0; i < pAd->ChannelListNum; i++) {
91980990 1366 if ((Channel == pAd->ChannelList[i].Channel)
96b3c83d 1367 && (pAd->ChannelList[i].RemainingTimeForUse == 0)) {
ec278fa2
BZ
1368 /* found radar signal in the channel. the channel can't use at least for 30 minutes. */
1369 pAd->ChannelList[i].RemainingTimeForUse = 1800; /*30 min = 1800 sec */
91980990
GKH
1370 Result = TRUE;
1371 break;
1372 }
1373 }
96b3c83d 1374 } while (FALSE);
91980990
GKH
1375
1376 return Result;
1377}
1378
51126deb
BZ
1379void NotifyChSwAnnToPeerAPs(IN PRTMP_ADAPTER pAd,
1380 u8 *pRA,
1381 u8 *pTA, u8 ChSwMode, u8 Channel)
91980990 1382{
91980990
GKH
1383}
1384
51126deb
BZ
1385static void StartDFSProcedure(IN PRTMP_ADAPTER pAd,
1386 u8 Channel, u8 ChSwMode)
91980990 1387{
ec278fa2 1388 /* start DFS procedure */
91980990 1389 pAd->CommonCfg.Channel = Channel;
1623267a 1390
91980990 1391 N_ChannelCheck(pAd);
1623267a 1392
91980990
GKH
1393 pAd->CommonCfg.RadarDetect.RDMode = RD_SWITCHING_MODE;
1394 pAd->CommonCfg.RadarDetect.CSCount = 0;
1395}
1396
1397/*
1398 ==========================================================================
1399 Description:
1400 Channel Switch Announcement action frame sanity check.
1401
1402 Parametrs:
1403 1. MLME message containing the received frame
1404 2. message length.
1405 3. Channel switch announcement infomation buffer.
1406
91980990
GKH
1407 Return : None.
1408 ==========================================================================
1409 */
1410
1411/*
1412 Channel Switch Announcement IE.
1413 +----+-----+-----------+------------+-----------+
1414 | ID | Len |Ch Sw Mode | New Ch Num | Ch Sw Cnt |
1415 +----+-----+-----------+------------+-----------+
1416 1 1 1 1 1
1417*/
96b3c83d 1418static BOOLEAN PeerChSwAnnSanity(IN PRTMP_ADAPTER pAd,
51126deb
BZ
1419 void * pMsg,
1420 unsigned long MsgLen,
96b3c83d 1421 OUT PCH_SW_ANN_INFO pChSwAnnInfo)
91980990 1422{
96b3c83d 1423 PFRAME_802_11 Fr = (PFRAME_802_11) pMsg;
51126deb 1424 u8 *pFramePtr = Fr->Octet;
91980990
GKH
1425 BOOLEAN result = FALSE;
1426 PEID_STRUCT eid_ptr;
1427
ec278fa2 1428 /* skip 802.11 header. */
91980990
GKH
1429 MsgLen -= sizeof(HEADER_802_11);
1430
ec278fa2 1431 /* skip category and action code. */
91980990
GKH
1432 pFramePtr += 2;
1433 MsgLen -= 2;
1434
1435 if (pChSwAnnInfo == NULL)
1436 return result;
1437
96b3c83d 1438 eid_ptr = (PEID_STRUCT) pFramePtr;
51126deb
BZ
1439 while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1440 ((u8 *)pFramePtr + MsgLen)) {
96b3c83d
BZ
1441 switch (eid_ptr->Eid) {
1442 case IE_CHANNEL_SWITCH_ANNOUNCEMENT:
1443 NdisMoveMemory(&pChSwAnnInfo->ChSwMode, eid_ptr->Octet,
1444 1);
1445 NdisMoveMemory(&pChSwAnnInfo->Channel,
1446 eid_ptr->Octet + 1, 1);
1447 NdisMoveMemory(&pChSwAnnInfo->ChSwCnt,
1448 eid_ptr->Octet + 2, 1);
1449
1450 result = TRUE;
1451 break;
91980990 1452
96b3c83d
BZ
1453 default:
1454 break;
91980990 1455 }
51126deb 1456 eid_ptr = (PEID_STRUCT) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
91980990
GKH
1457 }
1458
1459 return result;
1460}
1461
1462/*
1463 ==========================================================================
1464 Description:
1465 Measurement request action frame sanity check.
1466
1467 Parametrs:
1468 1. MLME message containing the received frame
1469 2. message length.
1470 3. Measurement request infomation buffer.
1471
1472 Return : None.
1473 ==========================================================================
1474 */
96b3c83d 1475static BOOLEAN PeerMeasureReqSanity(IN PRTMP_ADAPTER pAd,
51126deb
BZ
1476 void * pMsg,
1477 unsigned long MsgLen,
1478 u8 *pDialogToken,
96b3c83d
BZ
1479 OUT PMEASURE_REQ_INFO pMeasureReqInfo,
1480 OUT PMEASURE_REQ pMeasureReq)
91980990 1481{
96b3c83d 1482 PFRAME_802_11 Fr = (PFRAME_802_11) pMsg;
51126deb 1483 u8 *pFramePtr = Fr->Octet;
91980990
GKH
1484 BOOLEAN result = FALSE;
1485 PEID_STRUCT eid_ptr;
51126deb
BZ
1486 u8 *ptr;
1487 u64 MeasureStartTime;
1488 u16 MeasureDuration;
91980990 1489
ec278fa2 1490 /* skip 802.11 header. */
91980990
GKH
1491 MsgLen -= sizeof(HEADER_802_11);
1492
ec278fa2 1493 /* skip category and action code. */
91980990
GKH
1494 pFramePtr += 2;
1495 MsgLen -= 2;
1496
1497 if (pMeasureReqInfo == NULL)
1498 return result;
1499
1500 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1501 pFramePtr += 1;
1502 MsgLen -= 1;
1503
96b3c83d 1504 eid_ptr = (PEID_STRUCT) pFramePtr;
51126deb
BZ
1505 while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1506 ((u8 *)pFramePtr + MsgLen)) {
96b3c83d
BZ
1507 switch (eid_ptr->Eid) {
1508 case IE_MEASUREMENT_REQUEST:
1509 NdisMoveMemory(&pMeasureReqInfo->Token, eid_ptr->Octet,
1510 1);
1511 NdisMoveMemory(&pMeasureReqInfo->ReqMode.word,
1512 eid_ptr->Octet + 1, 1);
1513 NdisMoveMemory(&pMeasureReqInfo->ReqType,
1514 eid_ptr->Octet + 2, 1);
51126deb 1515 ptr = (u8 *)(eid_ptr->Octet + 3);
96b3c83d
BZ
1516 NdisMoveMemory(&pMeasureReq->ChNum, ptr, 1);
1517 NdisMoveMemory(&MeasureStartTime, ptr + 1, 8);
1518 pMeasureReq->MeasureStartTime =
1519 SWAP64(MeasureStartTime);
1520 NdisMoveMemory(&MeasureDuration, ptr + 9, 2);
1521 pMeasureReq->MeasureDuration = SWAP16(MeasureDuration);
1522
1523 result = TRUE;
1524 break;
91980990 1525
96b3c83d
BZ
1526 default:
1527 break;
91980990 1528 }
51126deb 1529 eid_ptr = (PEID_STRUCT) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
91980990
GKH
1530 }
1531
1532 return result;
1533}
1534
1535/*
1536 ==========================================================================
1537 Description:
1538 Measurement report action frame sanity check.
1539
1540 Parametrs:
1541 1. MLME message containing the received frame
1542 2. message length.
1543 3. Measurement report infomation buffer.
1544 4. basic report infomation buffer.
1545
1546 Return : None.
1547 ==========================================================================
1548 */
1549
1550/*
1551 Measurement Report IE.
1552 +----+-----+-------+-------------+--------------+----------------+
1553 | ID | Len | Token | Report Mode | Measure Type | Measure Report |
1554 +----+-----+-------+-------------+--------------+----------------+
1555 1 1 1 1 1 variable
1556
1557 Basic Report.
1558 +--------+------------+----------+-----+
1559 | Ch Num | Start Time | Duration | Map |
1560 +--------+------------+----------+-----+
1561 1 8 2 1
1562
1563 Map Field Bit Format.
1564 +-----+---------------+---------------------+-------+------------+----------+
1565 | Bss | OFDM Preamble | Unidentified signal | Radar | Unmeasured | Reserved |
1566 +-----+---------------+---------------------+-------+------------+----------+
1567 0 1 2 3 4 5-7
1568*/
96b3c83d 1569static BOOLEAN PeerMeasureReportSanity(IN PRTMP_ADAPTER pAd,
51126deb
BZ
1570 void * pMsg,
1571 unsigned long MsgLen,
1572 u8 *pDialogToken,
96b3c83d
BZ
1573 OUT PMEASURE_REPORT_INFO
1574 pMeasureReportInfo,
51126deb 1575 u8 *pReportBuf)
91980990 1576{
96b3c83d 1577 PFRAME_802_11 Fr = (PFRAME_802_11) pMsg;
51126deb 1578 u8 *pFramePtr = Fr->Octet;
91980990
GKH
1579 BOOLEAN result = FALSE;
1580 PEID_STRUCT eid_ptr;
51126deb 1581 u8 *ptr;
91980990 1582
ec278fa2 1583 /* skip 802.11 header. */
91980990
GKH
1584 MsgLen -= sizeof(HEADER_802_11);
1585
ec278fa2 1586 /* skip category and action code. */
91980990
GKH
1587 pFramePtr += 2;
1588 MsgLen -= 2;
1589
1590 if (pMeasureReportInfo == NULL)
1591 return result;
1592
1593 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1594 pFramePtr += 1;
1595 MsgLen -= 1;
1596
96b3c83d 1597 eid_ptr = (PEID_STRUCT) pFramePtr;
51126deb
BZ
1598 while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1599 ((u8 *)pFramePtr + MsgLen)) {
96b3c83d
BZ
1600 switch (eid_ptr->Eid) {
1601 case IE_MEASUREMENT_REPORT:
1602 NdisMoveMemory(&pMeasureReportInfo->Token,
1603 eid_ptr->Octet, 1);
1604 NdisMoveMemory(&pMeasureReportInfo->ReportMode,
1605 eid_ptr->Octet + 1, 1);
1606 NdisMoveMemory(&pMeasureReportInfo->ReportType,
1607 eid_ptr->Octet + 2, 1);
1608 if (pMeasureReportInfo->ReportType == RM_BASIC) {
1609 PMEASURE_BASIC_REPORT pReport =
1610 (PMEASURE_BASIC_REPORT) pReportBuf;
51126deb 1611 ptr = (u8 *)(eid_ptr->Octet + 3);
96b3c83d
BZ
1612 NdisMoveMemory(&pReport->ChNum, ptr, 1);
1613 NdisMoveMemory(&pReport->MeasureStartTime,
1614 ptr + 1, 8);
1615 NdisMoveMemory(&pReport->MeasureDuration,
1616 ptr + 9, 2);
1617 NdisMoveMemory(&pReport->Map, ptr + 11, 1);
1618
1619 } else if (pMeasureReportInfo->ReportType == RM_CCA) {
1620 PMEASURE_CCA_REPORT pReport =
1621 (PMEASURE_CCA_REPORT) pReportBuf;
51126deb 1622 ptr = (u8 *)(eid_ptr->Octet + 3);
96b3c83d
BZ
1623 NdisMoveMemory(&pReport->ChNum, ptr, 1);
1624 NdisMoveMemory(&pReport->MeasureStartTime,
1625 ptr + 1, 8);
1626 NdisMoveMemory(&pReport->MeasureDuration,
1627 ptr + 9, 2);
1628 NdisMoveMemory(&pReport->CCA_Busy_Fraction,
1629 ptr + 11, 1);
1630
1631 } else if (pMeasureReportInfo->ReportType ==
1632 RM_RPI_HISTOGRAM) {
1633 PMEASURE_RPI_REPORT pReport =
1634 (PMEASURE_RPI_REPORT) pReportBuf;
51126deb 1635 ptr = (u8 *)(eid_ptr->Octet + 3);
96b3c83d
BZ
1636 NdisMoveMemory(&pReport->ChNum, ptr, 1);
1637 NdisMoveMemory(&pReport->MeasureStartTime,
1638 ptr + 1, 8);
1639 NdisMoveMemory(&pReport->MeasureDuration,
1640 ptr + 9, 2);
1641 NdisMoveMemory(&pReport->RPI_Density, ptr + 11,
1642 8);
1643 }
1644 result = TRUE;
1645 break;
91980990 1646
96b3c83d
BZ
1647 default:
1648 break;
91980990 1649 }
51126deb 1650 eid_ptr = (PEID_STRUCT) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
91980990
GKH
1651 }
1652
1653 return result;
1654}
1655
1656/*
1657 ==========================================================================
1658 Description:
1659 TPC Request action frame sanity check.
1660
1661 Parametrs:
1662 1. MLME message containing the received frame
1663 2. message length.
1664 3. Dialog Token.
1665
1666 Return : None.
1667 ==========================================================================
1668 */
96b3c83d 1669static BOOLEAN PeerTpcReqSanity(IN PRTMP_ADAPTER pAd,
51126deb
BZ
1670 void * pMsg,
1671 unsigned long MsgLen, u8 *pDialogToken)
91980990 1672{
96b3c83d 1673 PFRAME_802_11 Fr = (PFRAME_802_11) pMsg;
51126deb 1674 u8 *pFramePtr = Fr->Octet;
91980990
GKH
1675 BOOLEAN result = FALSE;
1676 PEID_STRUCT eid_ptr;
1677
1678 MsgLen -= sizeof(HEADER_802_11);
1679
ec278fa2 1680 /* skip category and action code. */
91980990
GKH
1681 pFramePtr += 2;
1682 MsgLen -= 2;
1683
1684 if (pDialogToken == NULL)
1685 return result;
1686
1687 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1688 pFramePtr += 1;
1689 MsgLen -= 1;
1690
96b3c83d 1691 eid_ptr = (PEID_STRUCT) pFramePtr;
51126deb
BZ
1692 while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1693 ((u8 *)pFramePtr + MsgLen)) {
96b3c83d
BZ
1694 switch (eid_ptr->Eid) {
1695 case IE_TPC_REQUEST:
1696 result = TRUE;
1697 break;
91980990 1698
96b3c83d
BZ
1699 default:
1700 break;
91980990 1701 }
51126deb 1702 eid_ptr = (PEID_STRUCT) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
91980990
GKH
1703 }
1704
1705 return result;
1706}
1707
1708/*
1709 ==========================================================================
1710 Description:
1711 TPC Report action frame sanity check.
1712
1713 Parametrs:
1714 1. MLME message containing the received frame
1715 2. message length.
1716 3. Dialog Token.
1717 4. TPC Report IE.
1718
1719 Return : None.
1720 ==========================================================================
1721 */
96b3c83d 1722static BOOLEAN PeerTpcRepSanity(IN PRTMP_ADAPTER pAd,
51126deb
BZ
1723 void * pMsg,
1724 unsigned long MsgLen,
1725 u8 *pDialogToken,
96b3c83d 1726 OUT PTPC_REPORT_INFO pTpcRepInfo)
91980990 1727{
96b3c83d 1728 PFRAME_802_11 Fr = (PFRAME_802_11) pMsg;
51126deb 1729 u8 *pFramePtr = Fr->Octet;
91980990
GKH
1730 BOOLEAN result = FALSE;
1731 PEID_STRUCT eid_ptr;
1732
1733 MsgLen -= sizeof(HEADER_802_11);
1734
ec278fa2 1735 /* skip category and action code. */
91980990
GKH
1736 pFramePtr += 2;
1737 MsgLen -= 2;
1738
1739 if (pDialogToken == NULL)
1740 return result;
1741
1742 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1743 pFramePtr += 1;
1744 MsgLen -= 1;
1745
96b3c83d 1746 eid_ptr = (PEID_STRUCT) pFramePtr;
51126deb
BZ
1747 while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1748 ((u8 *)pFramePtr + MsgLen)) {
96b3c83d
BZ
1749 switch (eid_ptr->Eid) {
1750 case IE_TPC_REPORT:
1751 NdisMoveMemory(&pTpcRepInfo->TxPwr, eid_ptr->Octet, 1);
1752 NdisMoveMemory(&pTpcRepInfo->LinkMargin,
1753 eid_ptr->Octet + 1, 1);
1754 result = TRUE;
1755 break;
1756
1757 default:
1758 break;
91980990 1759 }
51126deb 1760 eid_ptr = (PEID_STRUCT) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
91980990
GKH
1761 }
1762
1763 return result;
1764}
1765
1766/*
1767 ==========================================================================
1768 Description:
1769 Channel Switch Announcement action frame handler.
1770
1771 Parametrs:
1772 Elme - MLME message containing the received frame
1773
1774 Return : None.
1775 ==========================================================================
1776 */
51126deb 1777static void PeerChSwAnnAction(IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM * Elem)
91980990
GKH
1778{
1779 CH_SW_ANN_INFO ChSwAnnInfo;
96b3c83d 1780 PFRAME_802_11 pFr = (PFRAME_802_11) Elem->Msg;
51126deb
BZ
1781 u8 index = 0, Channel = 0, NewChannel = 0;
1782 unsigned long Bssidx = 0;
91980990
GKH
1783
1784 NdisZeroMemory(&ChSwAnnInfo, sizeof(CH_SW_ANN_INFO));
96b3c83d
BZ
1785 if (!PeerChSwAnnSanity(pAd, Elem->Msg, Elem->MsgLen, &ChSwAnnInfo)) {
1786 DBGPRINT(RT_DEBUG_TRACE,
1787 ("Invalid Channel Switch Action Frame.\n"));
91980990
GKH
1788 return;
1789 }
1790
96b3c83d
BZ
1791 if (pAd->OpMode == OPMODE_STA) {
1792 Bssidx =
1793 BssTableSearch(&pAd->ScanTab, pFr->Hdr.Addr3,
1794 pAd->CommonCfg.Channel);
1795 if (Bssidx == BSS_NOT_FOUND) {
1796 DBGPRINT(RT_DEBUG_TRACE,
1797 ("PeerChSwAnnAction - Bssidx is not found\n"));
91980990
GKH
1798 return;
1799 }
1800
96b3c83d
BZ
1801 DBGPRINT(RT_DEBUG_TRACE,
1802 ("\n****Bssidx is %d, Channel = %d\n", index,
1803 pAd->ScanTab.BssEntry[Bssidx].Channel));
1804 hex_dump("SSID", pAd->ScanTab.BssEntry[Bssidx].Bssid, 6);
91980990
GKH
1805
1806 Channel = pAd->CommonCfg.Channel;
1807 NewChannel = ChSwAnnInfo.Channel;
1808
96b3c83d
BZ
1809 if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0)
1810 && (Channel != NewChannel)) {
ec278fa2
BZ
1811 /* Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection). */
1812 /* In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results. */
91980990
GKH
1813 AsicSwitchChannel(pAd, 1, FALSE);
1814 AsicLockChannel(pAd, 1);
96b3c83d 1815 LinkDown(pAd, FALSE);
91980990
GKH
1816 MlmeQueueInit(&pAd->Mlme.Queue);
1817 BssTableInit(&pAd->ScanTab);
ec278fa2 1818 RTMPusecDelay(1000000); /* use delay to prevent STA do reassoc */
91980990 1819
ec278fa2 1820 /* channel sanity check */
96b3c83d
BZ
1821 for (index = 0; index < pAd->ChannelListNum; index++) {
1822 if (pAd->ChannelList[index].Channel ==
1823 NewChannel) {
1824 pAd->ScanTab.BssEntry[Bssidx].Channel =
1825 NewChannel;
91980990 1826 pAd->CommonCfg.Channel = NewChannel;
96b3c83d
BZ
1827 AsicSwitchChannel(pAd,
1828 pAd->CommonCfg.
1829 Channel, FALSE);
1830 AsicLockChannel(pAd,
1831 pAd->CommonCfg.Channel);
1832 DBGPRINT(RT_DEBUG_TRACE,
1833 ("&&&&&&&&&&&&&&&&PeerChSwAnnAction - STA receive channel switch announcement IE (New Channel =%d)\n",
1834 NewChannel));
91980990
GKH
1835 break;
1836 }
1837 }
1838
96b3c83d 1839 if (index >= pAd->ChannelListNum) {
91980990
GKH
1840 DBGPRINT_ERR(("&&&&&&&&&&&&&&&&&&&&&&&&&&PeerChSwAnnAction(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum));
1841 }
1842 }
1843 }
91980990
GKH
1844
1845 return;
1846}
1847
91980990
GKH
1848/*
1849 ==========================================================================
1850 Description:
1851 Measurement Request action frame handler.
1852
1853 Parametrs:
1854 Elme - MLME message containing the received frame
1855
1856 Return : None.
1857 ==========================================================================
1858 */
51126deb 1859static void PeerMeasureReqAction(IN PRTMP_ADAPTER pAd,
96b3c83d 1860 IN MLME_QUEUE_ELEM * Elem)
91980990 1861{
96b3c83d 1862 PFRAME_802_11 pFr = (PFRAME_802_11) Elem->Msg;
51126deb 1863 u8 DialogToken;
91980990 1864 MEASURE_REQ_INFO MeasureReqInfo;
96b3c83d 1865 MEASURE_REQ MeasureReq;
91980990
GKH
1866 MEASURE_REPORT_MODE ReportMode;
1867
96b3c83d
BZ
1868 if (PeerMeasureReqSanity
1869 (pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReqInfo,
1870 &MeasureReq)) {
91980990
GKH
1871 ReportMode.word = 0;
1872 ReportMode.field.Incapable = 1;
96b3c83d
BZ
1873 EnqueueMeasurementRep(pAd, pFr->Hdr.Addr2, DialogToken,
1874 MeasureReqInfo.Token, ReportMode.word,
1875 MeasureReqInfo.ReqType, 0, NULL);
91980990
GKH
1876 }
1877
1878 return;
1879}
1880
1881/*
1882 ==========================================================================
1883 Description:
1884 Measurement Report action frame handler.
1885
1886 Parametrs:
1887 Elme - MLME message containing the received frame
1888
1889 Return : None.
1890 ==========================================================================
1891 */
51126deb 1892static void PeerMeasureReportAction(IN PRTMP_ADAPTER pAd,
96b3c83d 1893 IN MLME_QUEUE_ELEM * Elem)
91980990
GKH
1894{
1895 MEASURE_REPORT_INFO MeasureReportInfo;
96b3c83d 1896 PFRAME_802_11 pFr = (PFRAME_802_11) Elem->Msg;
51126deb
BZ
1897 u8 DialogToken;
1898 u8 *pMeasureReportInfo;
91980990 1899
ec278fa2
BZ
1900/* if (pAd->CommonCfg.bIEEE80211H != TRUE) */
1901/* return; */
91980990 1902
96b3c83d
BZ
1903 if ((pMeasureReportInfo =
1904 kmalloc(sizeof(MEASURE_RPI_REPORT), GFP_ATOMIC)) == NULL) {
1905 DBGPRINT(RT_DEBUG_ERROR,
1906 ("%s unable to alloc memory for measure report buffer (size=%zu).\n",
1907 __func__, sizeof(MEASURE_RPI_REPORT)));
91980990
GKH
1908 return;
1909 }
1910
1911 NdisZeroMemory(&MeasureReportInfo, sizeof(MEASURE_REPORT_INFO));
1912 NdisZeroMemory(pMeasureReportInfo, sizeof(MEASURE_RPI_REPORT));
96b3c83d
BZ
1913 if (PeerMeasureReportSanity
1914 (pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReportInfo,
1915 pMeasureReportInfo)) {
91980990
GKH
1916 do {
1917 PMEASURE_REQ_ENTRY pEntry = NULL;
1918
ec278fa2
BZ
1919 /* Not a autonomous measure report. */
1920 /* check the dialog token field. drop it if the dialog token doesn't match. */
91980990 1921 if ((DialogToken != 0)
96b3c83d
BZ
1922 && ((pEntry = MeasureReqLookUp(pAd, DialogToken)) ==
1923 NULL))
91980990
GKH
1924 break;
1925
1926 if (pEntry != NULL)
1927 MeasureReqDelete(pAd, pEntry->DialogToken);
1928
96b3c83d
BZ
1929 if (MeasureReportInfo.ReportType == RM_BASIC) {
1930 PMEASURE_BASIC_REPORT pBasicReport =
1931 (PMEASURE_BASIC_REPORT) pMeasureReportInfo;
91980990 1932 if ((pBasicReport->Map.field.Radar)
96b3c83d
BZ
1933 &&
1934 (DfsRequirementCheck
1935 (pAd, pBasicReport->ChNum) == TRUE)) {
1936 NotifyChSwAnnToPeerAPs(pAd,
1937 pFr->Hdr.Addr1,
1938 pFr->Hdr.Addr2,
1939 1,
1940 pBasicReport->
1941 ChNum);
1942 StartDFSProcedure(pAd,
1943 pBasicReport->ChNum,
1944 1);
91980990
GKH
1945 }
1946 }
1947 } while (FALSE);
96b3c83d
BZ
1948 } else
1949 DBGPRINT(RT_DEBUG_TRACE,
1950 ("Invalid Measurement Report Frame.\n"));
91980990
GKH
1951
1952 kfree(pMeasureReportInfo);
1953
1954 return;
1955}
1956
1957/*
1958 ==========================================================================
1959 Description:
1960 TPC Request action frame handler.
1961
1962 Parametrs:
1963 Elme - MLME message containing the received frame
1964
1965 Return : None.
1966 ==========================================================================
1967 */
51126deb 1968static void PeerTpcReqAction(IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM * Elem)
91980990 1969{
96b3c83d 1970 PFRAME_802_11 pFr = (PFRAME_802_11) Elem->Msg;
51126deb
BZ
1971 u8 *pFramePtr = pFr->Octet;
1972 u8 DialogToken;
1973 u8 TxPwr = GetCurTxPwr(pAd, Elem->Wcid);
1974 u8 LinkMargin = 0;
1975 char RealRssi;
91980990 1976
ec278fa2
BZ
1977 /* link margin: Ratio of the received signal power to the minimum desired by the station (STA). The */
1978 /* STA may incorporate rate information and channel conditions, including interference, into its computation */
1979 /* of link margin. */
91980990
GKH
1980
1981 RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0),
96b3c83d
BZ
1982 ConvertToRssi(pAd, Elem->Rssi1, RSSI_1),
1983 ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
91980990 1984
ec278fa2 1985 /* skip Category and action code. */
91980990
GKH
1986 pFramePtr += 2;
1987
ec278fa2 1988 /* Dialog token. */
91980990
GKH
1989 NdisMoveMemory(&DialogToken, pFramePtr, 1);
1990
1991 LinkMargin = (RealRssi / MIN_RCV_PWR);
1992 if (PeerTpcReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken))
96b3c83d
BZ
1993 EnqueueTPCRep(pAd, pFr->Hdr.Addr2, DialogToken, TxPwr,
1994 LinkMargin);
91980990
GKH
1995
1996 return;
1997}
1998
1999/*
2000 ==========================================================================
2001 Description:
2002 TPC Report action frame handler.
2003
2004 Parametrs:
2005 Elme - MLME message containing the received frame
2006
2007 Return : None.
2008 ==========================================================================
2009 */
51126deb 2010static void PeerTpcRepAction(IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM * Elem)
91980990 2011{
51126deb 2012 u8 DialogToken;
91980990
GKH
2013 TPC_REPORT_INFO TpcRepInfo;
2014 PTPC_REQ_ENTRY pEntry = NULL;
2015
2016 NdisZeroMemory(&TpcRepInfo, sizeof(TPC_REPORT_INFO));
96b3c83d
BZ
2017 if (PeerTpcRepSanity
2018 (pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &TpcRepInfo)) {
2019 if ((pEntry = TpcReqLookUp(pAd, DialogToken)) != NULL) {
91980990 2020 TpcReqDelete(pAd, pEntry->DialogToken);
96b3c83d
BZ
2021 DBGPRINT(RT_DEBUG_TRACE,
2022 ("%s: DialogToken=%x, TxPwr=%d, LinkMargin=%d\n",
2023 __func__, DialogToken, TpcRepInfo.TxPwr,
2024 TpcRepInfo.LinkMargin));
91980990
GKH
2025 }
2026 }
2027
2028 return;
2029}
2030
2031/*
2032 ==========================================================================
2033 Description:
2034 Spectrun action frames Handler such as channel switch annoucement,
2035 measurement report, measurement request actions frames.
2036
2037 Parametrs:
2038 Elme - MLME message containing the received frame
2039
2040 Return : None.
2041 ==========================================================================
2042 */
51126deb 2043void PeerSpectrumAction(IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM * Elem)
91980990
GKH
2044{
2045
51126deb 2046 u8 Action = Elem->Msg[LENGTH_802_11 + 1];
91980990
GKH
2047
2048 if (pAd->CommonCfg.bIEEE80211H != TRUE)
2049 return;
2050
96b3c83d
BZ
2051 switch (Action) {
2052 case SPEC_MRQ:
ec278fa2
BZ
2053 /* current rt2860 unable do such measure specified in Measurement Request. */
2054 /* reject all measurement request. */
96b3c83d
BZ
2055 PeerMeasureReqAction(pAd, Elem);
2056 break;
91980990 2057
96b3c83d
BZ
2058 case SPEC_MRP:
2059 PeerMeasureReportAction(pAd, Elem);
2060 break;
91980990 2061
96b3c83d
BZ
2062 case SPEC_TPCRQ:
2063 PeerTpcReqAction(pAd, Elem);
2064 break;
91980990 2065
96b3c83d
BZ
2066 case SPEC_TPCRP:
2067 PeerTpcRepAction(pAd, Elem);
2068 break;
91980990 2069
96b3c83d 2070 case SPEC_CHANNEL_SWITCH:
ca97b838 2071
96b3c83d
BZ
2072 PeerChSwAnnAction(pAd, Elem);
2073 break;
91980990
GKH
2074 }
2075
2076 return;
2077}
2078
2079/*
2080 ==========================================================================
2081 Description:
2082
2083 Parametrs:
2084
2085 Return : None.
2086 ==========================================================================
2087 */
51126deb 2088int Set_MeasureReq_Proc(IN PRTMP_ADAPTER pAd, char *arg)
91980990 2089{
51126deb
BZ
2090 u32 Aid = 1;
2091 u32 ArgIdx;
2092 char *thisChar;
91980990
GKH
2093
2094 MEASURE_REQ_MODE MeasureReqMode;
51126deb
BZ
2095 u8 MeasureReqToken = RandomByte(pAd);
2096 u8 MeasureReqType = RM_BASIC;
2097 u8 MeasureCh = 1;
2098 u64 MeasureStartTime = GetCurrentTimeStamp(pAd);
ca97b838 2099 MEASURE_REQ MeasureReq;
51126deb 2100 u8 TotalLen;
ca97b838
BZ
2101
2102 HEADER_802_11 ActHdr;
51126deb
BZ
2103 u8 *pOutBuffer = NULL;
2104 int NStatus;
2105 unsigned long FrameLen;
ca97b838 2106
51126deb 2107 NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */
96b3c83d
BZ
2108 if (NStatus != NDIS_STATUS_SUCCESS) {
2109 DBGPRINT(RT_DEBUG_TRACE,
2110 ("%s() allocate memory failed \n", __func__));
ca97b838
BZ
2111 goto END_OF_MEASURE_REQ;
2112 }
91980990
GKH
2113
2114 ArgIdx = 1;
96b3c83d
BZ
2115 while ((thisChar = strsep((char **)&arg, "-")) != NULL) {
2116 switch (ArgIdx) {
ec278fa2 2117 case 1: /* Aid. */
51126deb 2118 Aid = (u8)simple_strtol(thisChar, 0, 16);
96b3c83d 2119 break;
91980990 2120
ec278fa2 2121 case 2: /* Measurement Request Type. */
96b3c83d
BZ
2122 MeasureReqType = simple_strtol(thisChar, 0, 16);
2123 if (MeasureReqType > 3) {
2124 DBGPRINT(RT_DEBUG_ERROR,
2125 ("%s: unknow MeasureReqType(%d)\n",
2126 __func__, MeasureReqType));
2127 goto END_OF_MEASURE_REQ;
2128 }
2129 break;
91980990 2130
ec278fa2 2131 case 3: /* Measurement channel. */
51126deb 2132 MeasureCh = (u8)simple_strtol(thisChar, 0, 16);
96b3c83d 2133 break;
91980990
GKH
2134 }
2135 ArgIdx++;
2136 }
2137
96b3c83d
BZ
2138 DBGPRINT(RT_DEBUG_TRACE,
2139 ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", __func__,
2140 Aid, MeasureReqType, MeasureCh));
2141 if (!VALID_WCID(Aid)) {
2142 DBGPRINT(RT_DEBUG_ERROR,
2143 ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
ca97b838 2144 goto END_OF_MEASURE_REQ;
91980990
GKH
2145 }
2146
2147 MeasureReqMode.word = 0;
2148 MeasureReqMode.field.Enable = 1;
2149
2150 MeasureReqInsert(pAd, MeasureReqToken);
2151
ec278fa2 2152 /* build action frame header. */
96b3c83d
BZ
2153 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0,
2154 pAd->MacTab.Content[Aid].Addr, pAd->CurrentAddress);
ca97b838 2155
51126deb 2156 NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(HEADER_802_11));
ca97b838
BZ
2157 FrameLen = sizeof(HEADER_802_11);
2158
2159 TotalLen = sizeof(MEASURE_REQ_INFO) + sizeof(MEASURE_REQ);
2160
2161 MakeMeasurementReqFrame(pAd, pOutBuffer, &FrameLen,
96b3c83d
BZ
2162 sizeof(MEASURE_REQ_INFO), CATEGORY_RM, RM_BASIC,
2163 MeasureReqToken, MeasureReqMode.word,
2164 MeasureReqType, 0);
ca97b838
BZ
2165
2166 MeasureReq.ChNum = MeasureCh;
2167 MeasureReq.MeasureStartTime = cpu2le64(MeasureStartTime);
2168 MeasureReq.MeasureDuration = cpu2le16(2000);
2169
2170 {
51126deb 2171 unsigned long TempLen;
96b3c83d
BZ
2172 MakeOutgoingFrame(pOutBuffer + FrameLen, &TempLen,
2173 sizeof(MEASURE_REQ), &MeasureReq,
2174 END_OF_ARGS);
ca97b838
BZ
2175 FrameLen += TempLen;
2176 }
2177
51126deb 2178 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, (u32)FrameLen);
ca97b838
BZ
2179
2180END_OF_MEASURE_REQ:
2181 MlmeFreeMemory(pAd, pOutBuffer);
91980990
GKH
2182
2183 return TRUE;
2184}
2185
51126deb 2186int Set_TpcReq_Proc(IN PRTMP_ADAPTER pAd, char *arg)
91980990 2187{
51126deb 2188 u32 Aid;
91980990 2189
51126deb 2190 u8 TpcReqToken = RandomByte(pAd);
91980990 2191
51126deb 2192 Aid = (u32)simple_strtol(arg, 0, 16);
91980990 2193
d599edca 2194 DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d\n", __func__, Aid));
96b3c83d
BZ
2195 if (!VALID_WCID(Aid)) {
2196 DBGPRINT(RT_DEBUG_ERROR,
2197 ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
91980990
GKH
2198 return TRUE;
2199 }
2200
2201 TpcReqInsert(pAd, TpcReqToken);
2202
2203 EnqueueTPCReq(pAd, pAd->MacTab.Content[Aid].Addr, TpcReqToken);
2204
2205 return TRUE;
2206}