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