Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh...
[pandora-kernel.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     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
42 /* The regulatory information in the USA (US) */
43 struct rt_dot11_regulatory_information USARegulatoryInfo[] = {
44 /*  "regulatory class"  "number of channels"  "Max Tx Pwr"  "channel list" */
45         {0, {0, 0, {0}
46              }
47          }
48         ,                       /* Invlid entry */
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          }
96 };
97
98 #define USA_REGULATORY_INFO_SIZE (sizeof(USARegulatoryInfo) / sizeof(struct rt_dot11_regulatory_information))
99
100 /* The regulatory information in Europe */
101 struct rt_dot11_regulatory_information EuropeRegulatoryInfo[] = {
102 /*  "regulatory class"  "number of channels"  "Max Tx Pwr"  "channel list" */
103         {0, {0, 0, {0}
104              }
105          }
106         ,                       /* Invalid entry */
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          }
122 };
123
124 #define EU_REGULATORY_INFO_SIZE (sizeof(EuropeRegulatoryInfo) / sizeof(struct rt_dot11_regulatory_information))
125
126 /* The regulatory information in Japan */
127 struct rt_dot11_regulatory_information JapanRegulatoryInfo[] = {
128 /*  "regulatory class"  "number of channels"  "Max Tx Pwr"  "channel list" */
129         {0, {0, 0, {0}
130              }
131          }
132         ,                       /* Invalid entry */
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          }
260 };
261
262 #define JP_REGULATORY_INFO_SIZE (sizeof(JapanRegulatoryInfo) / sizeof(struct rt_dot11_regulatory_information))
263
264 char RTMP_GetTxPwr(struct rt_rtmp_adapter *pAd, IN HTTRANSMIT_SETTING HTTxMode)
265 {
266         struct tx_pwr_cfg {
267                 u8 Mode;
268                 u8 MCS;
269                 u16 req;
270                 u8 shift;
271                 u32 BitMask;
272         };
273
274         u32 Value;
275         int Idx;
276         u8 PhyMode;
277         char CurTxPwr;
278         u8 TxPwrRef = 0;
279         char DaltaPwr;
280         unsigned long TxPwr[5];
281
282         struct 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}
296                 , {MODE_HTMIX, 0, 1, 20, 0x00f00000},
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(struct tx_pwr_cfg))
314
315         CurTxPwr = 19;
316
317         /* check Tx Power setting from UI. */
318         if (pAd->CommonCfg.TxPowerPercentage > 90) ;
319         else if (pAd->CommonCfg.TxPowerPercentage > 60) /* reduce Pwr for 1 dB. */
320                 CurTxPwr -= 1;
321         else if (pAd->CommonCfg.TxPowerPercentage > 30) /* reduce Pwr for 3 dB. */
322                 CurTxPwr -= 3;
323         else if (pAd->CommonCfg.TxPowerPercentage > 15) /* reduce Pwr for 6 dB. */
324                 CurTxPwr -= 6;
325         else if (pAd->CommonCfg.TxPowerPercentage > 9)  /* reduce Pwr for 9 dB. */
326                 CurTxPwr -= 9;
327         else                    /* reduce Pwr for 12 dB. */
328                 CurTxPwr -= 12;
329
330         if (pAd->CommonCfg.BBPCurrentBW == BW_40) {
331                 if (pAd->CommonCfg.CentralChannel > 14) {
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];
337                 } else {
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                 }
344         } else {
345                 if (pAd->CommonCfg.Channel > 14) {
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];
351                 } else {
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
360         switch (HTTxMode.field.MODE) {
361         case MODE_CCK:
362         case MODE_OFDM:
363                 Value = TxPwr[1];
364                 TxPwrRef = (Value & 0x00000f00) >> 8;
365
366                 break;
367
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;
378         }
379
380         PhyMode = (HTTxMode.field.MODE == MODE_HTGREENFIELD)
381             ? MODE_HTMIX : HTTxMode.field.MODE;
382
383         for (Idx = 0; Idx < MAX_TXPWR_TAB_SIZE; Idx++) {
384                 if ((TxPwrCfg[Idx].Mode == PhyMode)
385                     && (TxPwrCfg[Idx].MCS == HTTxMode.field.MCS)) {
386                         Value = TxPwr[TxPwrCfg[Idx].req];
387                         DaltaPwr =
388                             TxPwrRef - (char)((Value & TxPwrCfg[Idx].BitMask)
389                                                >> TxPwrCfg[Idx].shift);
390                         CurTxPwr -= DaltaPwr;
391                         break;
392                 }
393         }
394
395         return CurTxPwr;
396 }
397
398 void MeasureReqTabInit(struct rt_rtmp_adapter *pAd)
399 {
400         NdisAllocateSpinLock(&pAd->CommonCfg.MeasureReqTabLock);
401
402         pAd->CommonCfg.pMeasureReqTab =
403             kmalloc(sizeof(struct rt_measure_req_tab), GFP_ATOMIC);
404         if (pAd->CommonCfg.pMeasureReqTab)
405                 NdisZeroMemory(pAd->CommonCfg.pMeasureReqTab,
406                                sizeof(struct rt_measure_req_tab));
407         else
408                 DBGPRINT(RT_DEBUG_ERROR,
409                          ("%s Fail to alloc memory for pAd->CommonCfg.pMeasureReqTab.\n",
410                           __func__));
411
412         return;
413 }
414
415 void MeasureReqTabExit(struct rt_rtmp_adapter *pAd)
416 {
417         NdisFreeSpinLock(&pAd->CommonCfg.MeasureReqTabLock);
418
419         if (pAd->CommonCfg.pMeasureReqTab)
420                 kfree(pAd->CommonCfg.pMeasureReqTab);
421         pAd->CommonCfg.pMeasureReqTab = NULL;
422
423         return;
424 }
425
426 struct rt_measure_req_entry *MeasureReqLookUp(struct rt_rtmp_adapter *pAd, u8 DialogToken)
427 {
428         u32 HashIdx;
429         struct rt_measure_req_tab *pTab = pAd->CommonCfg.pMeasureReqTab;
430         struct rt_measure_req_entry *pEntry = NULL;
431         struct rt_measure_req_entry *pPrevEntry = NULL;
432
433         if (pTab == NULL) {
434                 DBGPRINT(RT_DEBUG_ERROR,
435                          ("%s: pMeasureReqTab doesn't exist.\n", __func__));
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
444         while (pEntry) {
445                 if (pEntry->DialogToken == DialogToken)
446                         break;
447                 else {
448                         pPrevEntry = pEntry;
449                         pEntry = pEntry->pNext;
450                 }
451         }
452
453         RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
454
455         return pEntry;
456 }
457
458 struct rt_measure_req_entry *MeasureReqInsert(struct rt_rtmp_adapter *pAd, u8 DialogToken)
459 {
460         int i;
461         unsigned long HashIdx;
462         struct rt_measure_req_tab *pTab = pAd->CommonCfg.pMeasureReqTab;
463         struct rt_measure_req_entry *pEntry = NULL, *pCurrEntry;
464         unsigned long Now;
465
466         if (pTab == NULL) {
467                 DBGPRINT(RT_DEBUG_ERROR,
468                          ("%s: pMeasureReqTab doesn't exist.\n", __func__));
469                 return NULL;
470         }
471
472         pEntry = MeasureReqLookUp(pAd, DialogToken);
473         if (pEntry == NULL) {
474                 RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
475                 for (i = 0; i < MAX_MEASURE_REQ_TAB_SIZE; i++) {
476                         NdisGetSystemUpTime(&Now);
477                         pEntry = &pTab->Content[i];
478
479                         if ((pEntry->Valid == TRUE)
480                             && RTMP_TIME_AFTER((unsigned long)Now,
481                                                (unsigned long)(pEntry->
482                                                                lastTime +
483                                                                MQ_REQ_AGE_OUT)))
484                         {
485                                 struct rt_measure_req_entry *pPrevEntry = NULL;
486                                 unsigned long HashIdx =
487                                     MQ_DIALOGTOKEN_HASH_INDEX(pEntry->
488                                                               DialogToken);
489                                 struct rt_measure_req_entry *pProbeEntry =
490                                     pTab->Hash[HashIdx];
491
492                                 /* update Hash list */
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;
501                                                 }
502                                                 break;
503                                         }
504
505                                         pPrevEntry = pProbeEntry;
506                                         pProbeEntry = pProbeEntry->pNext;
507                                 } while (pProbeEntry);
508
509                                 NdisZeroMemory(pEntry,
510                                                sizeof(struct rt_measure_req_entry));
511                                 pTab->Size--;
512
513                                 break;
514                         }
515
516                         if (pEntry->Valid == FALSE)
517                                 break;
518                 }
519
520                 if (i < MAX_MEASURE_REQ_TAB_SIZE) {
521                         NdisGetSystemUpTime(&Now);
522                         pEntry->lastTime = Now;
523                         pEntry->Valid = TRUE;
524                         pEntry->DialogToken = DialogToken;
525                         pTab->Size++;
526                 } else {
527                         pEntry = NULL;
528                         DBGPRINT(RT_DEBUG_ERROR,
529                                  ("%s: pMeasureReqTab tab full.\n", __func__));
530                 }
531
532                 /* add this Neighbor entry into HASH table */
533                 if (pEntry) {
534                         HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken);
535                         if (pTab->Hash[HashIdx] == NULL) {
536                                 pTab->Hash[HashIdx] = pEntry;
537                         } else {
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
551 void MeasureReqDelete(struct rt_rtmp_adapter *pAd, u8 DialogToken)
552 {
553         struct rt_measure_req_tab *pTab = pAd->CommonCfg.pMeasureReqTab;
554         struct rt_measure_req_entry *pEntry = NULL;
555
556         if (pTab == NULL) {
557                 DBGPRINT(RT_DEBUG_ERROR,
558                          ("%s: pMeasureReqTab doesn't exist.\n", __func__));
559                 return;
560         }
561         /* if empty, return */
562         if (pTab->Size == 0) {
563                 DBGPRINT(RT_DEBUG_ERROR, ("pMeasureReqTab empty.\n"));
564                 return;
565         }
566
567         pEntry = MeasureReqLookUp(pAd, DialogToken);
568         if (pEntry != NULL) {
569                 struct rt_measure_req_entry *pPrevEntry = NULL;
570                 unsigned long HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
571                 struct rt_measure_req_entry *pProbeEntry = pTab->Hash[HashIdx];
572
573                 RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
574                 /* update Hash list */
575                 do {
576                         if (pProbeEntry == pEntry) {
577                                 if (pPrevEntry == NULL) {
578                                         pTab->Hash[HashIdx] = pEntry->pNext;
579                                 } else {
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(struct rt_measure_req_entry));
590                 pTab->Size--;
591
592                 RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
593         }
594
595         return;
596 }
597
598 void TpcReqTabInit(struct rt_rtmp_adapter *pAd)
599 {
600         NdisAllocateSpinLock(&pAd->CommonCfg.TpcReqTabLock);
601
602         pAd->CommonCfg.pTpcReqTab = kmalloc(sizeof(struct rt_tpc_req_tab), GFP_ATOMIC);
603         if (pAd->CommonCfg.pTpcReqTab)
604                 NdisZeroMemory(pAd->CommonCfg.pTpcReqTab, sizeof(struct rt_tpc_req_tab));
605         else
606                 DBGPRINT(RT_DEBUG_ERROR,
607                          ("%s Fail to alloc memory for pAd->CommonCfg.pTpcReqTab.\n",
608                           __func__));
609
610         return;
611 }
612
613 void TpcReqTabExit(struct rt_rtmp_adapter *pAd)
614 {
615         NdisFreeSpinLock(&pAd->CommonCfg.TpcReqTabLock);
616
617         if (pAd->CommonCfg.pTpcReqTab)
618                 kfree(pAd->CommonCfg.pTpcReqTab);
619         pAd->CommonCfg.pTpcReqTab = NULL;
620
621         return;
622 }
623
624 static struct rt_tpc_req_entry *TpcReqLookUp(struct rt_rtmp_adapter *pAd, u8 DialogToken)
625 {
626         u32 HashIdx;
627         struct rt_tpc_req_tab *pTab = pAd->CommonCfg.pTpcReqTab;
628         struct rt_tpc_req_entry *pEntry = NULL;
629         struct rt_tpc_req_entry *pPrevEntry = NULL;
630
631         if (pTab == NULL) {
632                 DBGPRINT(RT_DEBUG_ERROR,
633                          ("%s: pTpcReqTab doesn't exist.\n", __func__));
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
642         while (pEntry) {
643                 if (pEntry->DialogToken == DialogToken)
644                         break;
645                 else {
646                         pPrevEntry = pEntry;
647                         pEntry = pEntry->pNext;
648                 }
649         }
650
651         RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
652
653         return pEntry;
654 }
655
656 static struct rt_tpc_req_entry *TpcReqInsert(struct rt_rtmp_adapter *pAd, u8 DialogToken)
657 {
658         int i;
659         unsigned long HashIdx;
660         struct rt_tpc_req_tab *pTab = pAd->CommonCfg.pTpcReqTab;
661         struct rt_tpc_req_entry *pEntry = NULL, *pCurrEntry;
662         unsigned long Now;
663
664         if (pTab == NULL) {
665                 DBGPRINT(RT_DEBUG_ERROR,
666                          ("%s: pTpcReqTab doesn't exist.\n", __func__));
667                 return NULL;
668         }
669
670         pEntry = TpcReqLookUp(pAd, DialogToken);
671         if (pEntry == NULL) {
672                 RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
673                 for (i = 0; i < MAX_TPC_REQ_TAB_SIZE; i++) {
674                         NdisGetSystemUpTime(&Now);
675                         pEntry = &pTab->Content[i];
676
677                         if ((pEntry->Valid == TRUE)
678                             && RTMP_TIME_AFTER((unsigned long)Now,
679                                                (unsigned long)(pEntry->
680                                                                lastTime +
681                                                                TPC_REQ_AGE_OUT)))
682                         {
683                                 struct rt_tpc_req_entry *pPrevEntry = NULL;
684                                 unsigned long HashIdx =
685                                     TPC_DIALOGTOKEN_HASH_INDEX(pEntry->
686                                                                DialogToken);
687                                 struct rt_tpc_req_entry *pProbeEntry =
688                                     pTab->Hash[HashIdx];
689
690                                 /* update Hash list */
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;
699                                                 }
700                                                 break;
701                                         }
702
703                                         pPrevEntry = pProbeEntry;
704                                         pProbeEntry = pProbeEntry->pNext;
705                                 } while (pProbeEntry);
706
707                                 NdisZeroMemory(pEntry, sizeof(struct rt_tpc_req_entry));
708                                 pTab->Size--;
709
710                                 break;
711                         }
712
713                         if (pEntry->Valid == FALSE)
714                                 break;
715                 }
716
717                 if (i < MAX_TPC_REQ_TAB_SIZE) {
718                         NdisGetSystemUpTime(&Now);
719                         pEntry->lastTime = Now;
720                         pEntry->Valid = TRUE;
721                         pEntry->DialogToken = DialogToken;
722                         pTab->Size++;
723                 } else {
724                         pEntry = NULL;
725                         DBGPRINT(RT_DEBUG_ERROR,
726                                  ("%s: pTpcReqTab tab full.\n", __func__));
727                 }
728
729                 /* add this Neighbor entry into HASH table */
730                 if (pEntry) {
731                         HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken);
732                         if (pTab->Hash[HashIdx] == NULL) {
733                                 pTab->Hash[HashIdx] = pEntry;
734                         } else {
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
748 static void TpcReqDelete(struct rt_rtmp_adapter *pAd, u8 DialogToken)
749 {
750         struct rt_tpc_req_tab *pTab = pAd->CommonCfg.pTpcReqTab;
751         struct rt_tpc_req_entry *pEntry = NULL;
752
753         if (pTab == NULL) {
754                 DBGPRINT(RT_DEBUG_ERROR,
755                          ("%s: pTpcReqTab doesn't exist.\n", __func__));
756                 return;
757         }
758         /* if empty, return */
759         if (pTab->Size == 0) {
760                 DBGPRINT(RT_DEBUG_ERROR, ("pTpcReqTab empty.\n"));
761                 return;
762         }
763
764         pEntry = TpcReqLookUp(pAd, DialogToken);
765         if (pEntry != NULL) {
766                 struct rt_tpc_req_entry *pPrevEntry = NULL;
767                 unsigned long HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
768                 struct rt_tpc_req_entry *pProbeEntry = pTab->Hash[HashIdx];
769
770                 RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
771                 /* update Hash list */
772                 do {
773                         if (pProbeEntry == pEntry) {
774                                 if (pPrevEntry == NULL) {
775                                         pTab->Hash[HashIdx] = pEntry->pNext;
776                                 } else {
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(struct rt_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  */
805 static u64 GetCurrentTimeStamp(struct rt_rtmp_adapter *pAd)
806 {
807         /* get current time stamp. */
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  */
821 static u8 GetCurTxPwr(struct rt_rtmp_adapter *pAd, u8 Wcid)
822 {
823         return 16;              /* 16 dBm */
824 }
825
826 /*
827         ==========================================================================
828         Description:
829                 Get Current Transmit Power.
830
831         Parametrs:
832
833         Return  : Current Time Stamp.
834         ==========================================================================
835  */
836 void InsertChannelRepIE(struct rt_rtmp_adapter *pAd,
837                         u8 *pFrameBuf,
838                         unsigned long *pFrameLen,
839                         char *pCountry, u8 RegulatoryClass)
840 {
841         unsigned long TempLen;
842         u8 Len;
843         u8 IEId = IE_AP_CHANNEL_REPORT;
844         u8 *pChListPtr = NULL;
845
846         Len = 1;
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));
852                         return;
853                 }
854
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));
865                         return;
866                 }
867
868                 Len +=
869                     JapanRegulatoryInfo[RegulatoryClass].ChannelSet.
870                     NumberOfChannels;
871                 pChListPtr =
872                     JapanRegulatoryInfo[RegulatoryClass].ChannelSet.ChannelList;
873         } else {
874                 DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow Country (%s)\n",
875                                           __func__, pCountry));
876                 return;
877         }
878
879         MakeOutgoingFrame(pFrameBuf, &TempLen,
880                           1, &IEId,
881                           1, &Len,
882                           1, &RegulatoryClass,
883                           Len - 1, pChListPtr, END_OF_ARGS);
884
885         *pFrameLen = *pFrameLen + TempLen;
886
887         return;
888 }
889
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  */
903 void InsertDialogToken(struct rt_rtmp_adapter *pAd,
904                        u8 *pFrameBuf,
905                        unsigned long *pFrameLen, u8 DialogToken)
906 {
907         unsigned long TempLen;
908         MakeOutgoingFrame(pFrameBuf, &TempLen, 1, &DialogToken, END_OF_ARGS);
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  */
927 static void InsertTpcReqIE(struct rt_rtmp_adapter *pAd,
928                            u8 *pFrameBuf, unsigned long *pFrameLen)
929 {
930         unsigned long TempLen;
931         unsigned long Len = 0;
932         u8 ElementID = IE_TPC_REQUEST;
933
934         MakeOutgoingFrame(pFrameBuf, &TempLen,
935                           1, &ElementID, 1, &Len, END_OF_ARGS);
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  */
956 void InsertTpcReportIE(struct rt_rtmp_adapter *pAd,
957                        u8 *pFrameBuf,
958                        unsigned long *pFrameLen,
959                        u8 TxPwr, u8 LinkMargin)
960 {
961         unsigned long TempLen;
962         unsigned long Len = sizeof(struct rt_tpc_report_info);
963         u8 ElementID = IE_TPC_REPORT;
964         struct rt_tpc_report_info TpcReportIE;
965
966         TpcReportIE.TxPwr = TxPwr;
967         TpcReportIE.LinkMargin = LinkMargin;
968
969         MakeOutgoingFrame(pFrameBuf, &TempLen,
970                           1, &ElementID,
971                           1, &Len, Len, &TpcReportIE, END_OF_ARGS);
972
973         *pFrameLen = *pFrameLen + TempLen;
974
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  */
993 static void InsertChSwAnnIE(struct rt_rtmp_adapter *pAd,
994                             u8 *pFrameBuf,
995                             unsigned long *pFrameLen,
996                             u8 ChSwMode,
997                             u8 NewChannel, u8 ChSwCnt)
998 {
999         unsigned long TempLen;
1000         unsigned long Len = sizeof(struct rt_ch_sw_ann_info);
1001         u8 ElementID = IE_CHANNEL_SWITCH_ANNOUNCEMENT;
1002         struct rt_ch_sw_ann_info ChSwAnnIE;
1003
1004         ChSwAnnIE.ChSwMode = ChSwMode;
1005         ChSwAnnIE.Channel = NewChannel;
1006         ChSwAnnIE.ChSwCnt = ChSwCnt;
1007
1008         MakeOutgoingFrame(pFrameBuf, &TempLen,
1009                           1, &ElementID, 1, &Len, Len, &ChSwAnnIE, END_OF_ARGS);
1010
1011         *pFrameLen = *pFrameLen + TempLen;
1012
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
1031         Return  : None.
1032         ==========================================================================
1033  */
1034 static void InsertMeasureReqIE(struct rt_rtmp_adapter *pAd,
1035                                u8 *pFrameBuf,
1036                                unsigned long *pFrameLen,
1037                                u8 Len, struct rt_measure_req_info * pMeasureReqIE)
1038 {
1039         unsigned long TempLen;
1040         u8 ElementID = IE_MEASUREMENT_REQUEST;
1041
1042         MakeOutgoingFrame(pFrameBuf, &TempLen,
1043                           1, &ElementID,
1044                           1, &Len,
1045                           sizeof(struct rt_measure_req_info), pMeasureReqIE, END_OF_ARGS);
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  */
1069 static void InsertMeasureReportIE(struct rt_rtmp_adapter *pAd,
1070                                   u8 *pFrameBuf,
1071                                   unsigned long *pFrameLen,
1072                                   struct rt_measure_report_info * pMeasureReportIE,
1073                                   u8 ReportLnfoLen, u8 *pReportInfo)
1074 {
1075         unsigned long TempLen;
1076         unsigned long Len;
1077         u8 ElementID = IE_MEASUREMENT_REPORT;
1078
1079         Len = sizeof(struct rt_measure_report_info) + ReportLnfoLen;
1080
1081         MakeOutgoingFrame(pFrameBuf, &TempLen,
1082                           1, &ElementID,
1083                           1, &Len, Len, pMeasureReportIE, END_OF_ARGS);
1084
1085         *pFrameLen = *pFrameLen + TempLen;
1086
1087         if ((ReportLnfoLen > 0) && (pReportInfo != NULL)) {
1088                 MakeOutgoingFrame(pFrameBuf + *pFrameLen, &TempLen,
1089                                   ReportLnfoLen, pReportInfo, END_OF_ARGS);
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  */
1108 void MakeMeasurementReqFrame(struct rt_rtmp_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)
1117 {
1118         unsigned long TempLen;
1119         struct rt_measure_req_info MeasureReqIE;
1120
1121         InsertActField(pAd, (pOutBuffer + *pFrameLen), pFrameLen, Category,
1122                        Action);
1123
1124         /* fill Dialog Token */
1125         InsertDialogToken(pAd, (pOutBuffer + *pFrameLen), pFrameLen,
1126                           MeasureToken);
1127
1128         /* fill Number of repetitions. */
1129         if (Category == CATEGORY_RM) {
1130                 MakeOutgoingFrame((pOutBuffer + *pFrameLen), &TempLen,
1131                                   2, &NumOfRepetitions, END_OF_ARGS);
1132
1133                 *pFrameLen += TempLen;
1134         }
1135         /* prepare Measurement IE. */
1136         NdisZeroMemory(&MeasureReqIE, sizeof(struct rt_measure_req_info));
1137         MeasureReqIE.Token = MeasureToken;
1138         MeasureReqIE.ReqMode.word = MeasureReqMode;
1139         MeasureReqIE.ReqType = MeasureReqType;
1140         InsertMeasureReqIE(pAd, (pOutBuffer + *pFrameLen), pFrameLen,
1141                            TotalLen, &MeasureReqIE);
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  */
1158 void EnqueueMeasurementRep(struct rt_rtmp_adapter *pAd,
1159                            u8 *pDA,
1160                            u8 DialogToken,
1161                            u8 MeasureToken,
1162                            u8 MeasureReqMode,
1163                            u8 MeasureReqType,
1164                            u8 ReportInfoLen, u8 *pReportInfo)
1165 {
1166         u8 *pOutBuffer = NULL;
1167         int NStatus;
1168         unsigned long FrameLen;
1169         struct rt_header_802_11 ActHdr;
1170         struct rt_measure_report_info MeasureRepIE;
1171
1172         /* build action frame header. */
1173         MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1174                          pAd->CurrentAddress);
1175
1176         NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer);        /*Get an unused nonpaged memory */
1177         if (NStatus != NDIS_STATUS_SUCCESS) {
1178                 DBGPRINT(RT_DEBUG_TRACE,
1179                          ("%s() allocate memory failed \n", __func__));
1180                 return;
1181         }
1182         NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11));
1183         FrameLen = sizeof(struct rt_header_802_11);
1184
1185         InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen,
1186                        CATEGORY_SPECTRUM, SPEC_MRP);
1187
1188         /* fill Dialog Token */
1189         InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
1190
1191         /* prepare Measurement IE. */
1192         NdisZeroMemory(&MeasureRepIE, sizeof(struct rt_measure_report_info));
1193         MeasureRepIE.Token = MeasureToken;
1194         MeasureRepIE.ReportMode = MeasureReqMode;
1195         MeasureRepIE.ReportType = MeasureReqType;
1196         InsertMeasureReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen,
1197                               &MeasureRepIE, ReportInfoLen, pReportInfo);
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  */
1217 void EnqueueTPCReq(struct rt_rtmp_adapter *pAd, u8 *pDA, u8 DialogToken)
1218 {
1219         u8 *pOutBuffer = NULL;
1220         int NStatus;
1221         unsigned long FrameLen;
1222
1223         struct rt_header_802_11 ActHdr;
1224
1225         /* build action frame header. */
1226         MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1227                          pAd->CurrentAddress);
1228
1229         NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer);        /*Get an unused nonpaged memory */
1230         if (NStatus != NDIS_STATUS_SUCCESS) {
1231                 DBGPRINT(RT_DEBUG_TRACE,
1232                          ("%s() allocate memory failed \n", __func__));
1233                 return;
1234         }
1235         NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11));
1236         FrameLen = sizeof(struct rt_header_802_11);
1237
1238         InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen,
1239                        CATEGORY_SPECTRUM, SPEC_TPCRQ);
1240
1241         /* fill Dialog Token */
1242         InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
1243
1244         /* Insert TPC Request IE. */
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  */
1265 void EnqueueTPCRep(struct rt_rtmp_adapter *pAd,
1266                    u8 *pDA,
1267                    u8 DialogToken, u8 TxPwr, u8 LinkMargin)
1268 {
1269         u8 *pOutBuffer = NULL;
1270         int NStatus;
1271         unsigned long FrameLen;
1272
1273         struct rt_header_802_11 ActHdr;
1274
1275         /* build action frame header. */
1276         MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1277                          pAd->CurrentAddress);
1278
1279         NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer);        /*Get an unused nonpaged memory */
1280         if (NStatus != NDIS_STATUS_SUCCESS) {
1281                 DBGPRINT(RT_DEBUG_TRACE,
1282                          ("%s() allocate memory failed \n", __func__));
1283                 return;
1284         }
1285         NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11));
1286         FrameLen = sizeof(struct rt_header_802_11);
1287
1288         InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen,
1289                        CATEGORY_SPECTRUM, SPEC_TPCRP);
1290
1291         /* fill Dialog Token */
1292         InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
1293
1294         /* Insert TPC Request IE. */
1295         InsertTpcReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, TxPwr,
1296                           LinkMargin);
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  */
1318 void EnqueueChSwAnn(struct rt_rtmp_adapter *pAd,
1319                     u8 *pDA, u8 ChSwMode, u8 NewCh)
1320 {
1321         u8 *pOutBuffer = NULL;
1322         int NStatus;
1323         unsigned long FrameLen;
1324
1325         struct rt_header_802_11 ActHdr;
1326
1327         /* build action frame header. */
1328         MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1329                          pAd->CurrentAddress);
1330
1331         NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer);        /*Get an unused nonpaged memory */
1332         if (NStatus != NDIS_STATUS_SUCCESS) {
1333                 DBGPRINT(RT_DEBUG_TRACE,
1334                          ("%s() allocate memory failed \n", __func__));
1335                 return;
1336         }
1337         NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11));
1338         FrameLen = sizeof(struct rt_header_802_11);
1339
1340         InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen,
1341                        CATEGORY_SPECTRUM, SPEC_CHANNEL_SWITCH);
1342
1343         InsertChSwAnnIE(pAd, (pOutBuffer + FrameLen), &FrameLen, ChSwMode,
1344                         NewCh, 0);
1345
1346         MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1347         MlmeFreeMemory(pAd, pOutBuffer);
1348
1349         return;
1350 }
1351
1352 static BOOLEAN DfsRequirementCheck(struct rt_rtmp_adapter *pAd, u8 Channel)
1353 {
1354         BOOLEAN Result = FALSE;
1355         int i;
1356
1357         do {
1358                 /* check DFS procedure is running. */
1359                 /* make sure DFS procedure won't start twice. */
1360                 if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE) {
1361                         Result = FALSE;
1362                         break;
1363                 }
1364                 /* check the new channel carried from Channel Switch Announcemnet is valid. */
1365                 for (i = 0; i < pAd->ChannelListNum; i++) {
1366                         if ((Channel == pAd->ChannelList[i].Channel)
1367                             && (pAd->ChannelList[i].RemainingTimeForUse == 0)) {
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 */
1370                                 Result = TRUE;
1371                                 break;
1372                         }
1373                 }
1374         } while (FALSE);
1375
1376         return Result;
1377 }
1378
1379 void NotifyChSwAnnToPeerAPs(struct rt_rtmp_adapter *pAd,
1380                             u8 *pRA,
1381                             u8 *pTA, u8 ChSwMode, u8 Channel)
1382 {
1383 }
1384
1385 static void StartDFSProcedure(struct rt_rtmp_adapter *pAd,
1386                               u8 Channel, u8 ChSwMode)
1387 {
1388         /* start DFS procedure */
1389         pAd->CommonCfg.Channel = Channel;
1390
1391         N_ChannelCheck(pAd);
1392
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
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 */
1418 static BOOLEAN PeerChSwAnnSanity(struct rt_rtmp_adapter *pAd,
1419                                  void * pMsg,
1420                                  unsigned long MsgLen,
1421                                  struct rt_ch_sw_ann_info * pChSwAnnInfo)
1422 {
1423         struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg;
1424         u8 *pFramePtr = Fr->Octet;
1425         BOOLEAN result = FALSE;
1426         struct rt_eid * eid_ptr;
1427
1428         /* skip 802.11 header. */
1429         MsgLen -= sizeof(struct rt_header_802_11);
1430
1431         /* skip category and action code. */
1432         pFramePtr += 2;
1433         MsgLen -= 2;
1434
1435         if (pChSwAnnInfo == NULL)
1436                 return result;
1437
1438         eid_ptr = (struct rt_eid *) pFramePtr;
1439         while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1440                ((u8 *)pFramePtr + MsgLen)) {
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;
1452
1453                 default:
1454                         break;
1455                 }
1456                 eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
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  */
1475 static BOOLEAN PeerMeasureReqSanity(struct rt_rtmp_adapter *pAd,
1476                                     void * pMsg,
1477                                     unsigned long MsgLen,
1478                                     u8 *pDialogToken,
1479                                     struct rt_measure_req_info * pMeasureReqInfo,
1480                                     struct rt_measure_req * pMeasureReq)
1481 {
1482         struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg;
1483         u8 *pFramePtr = Fr->Octet;
1484         BOOLEAN result = FALSE;
1485         struct rt_eid * eid_ptr;
1486         u8 *ptr;
1487         u64 MeasureStartTime;
1488         u16 MeasureDuration;
1489
1490         /* skip 802.11 header. */
1491         MsgLen -= sizeof(struct rt_header_802_11);
1492
1493         /* skip category and action code. */
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
1504         eid_ptr = (struct rt_eid *) pFramePtr;
1505         while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1506                ((u8 *)pFramePtr + MsgLen)) {
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);
1515                         ptr = (u8 *)(eid_ptr->Octet + 3);
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;
1525
1526                 default:
1527                         break;
1528                 }
1529                 eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
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 */
1569 static BOOLEAN PeerMeasureReportSanity(struct rt_rtmp_adapter *pAd,
1570                                        void * pMsg,
1571                                        unsigned long MsgLen,
1572                                        u8 *pDialogToken,
1573                                        struct rt_measure_report_info *
1574                                        pMeasureReportInfo,
1575                                        u8 *pReportBuf)
1576 {
1577         struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg;
1578         u8 *pFramePtr = Fr->Octet;
1579         BOOLEAN result = FALSE;
1580         struct rt_eid * eid_ptr;
1581         u8 *ptr;
1582
1583         /* skip 802.11 header. */
1584         MsgLen -= sizeof(struct rt_header_802_11);
1585
1586         /* skip category and action code. */
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
1597         eid_ptr = (struct rt_eid *) pFramePtr;
1598         while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1599                ((u8 *)pFramePtr + MsgLen)) {
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                                 struct rt_measure_basic_report * pReport =
1610                                     (struct rt_measure_basic_report *) pReportBuf;
1611                                 ptr = (u8 *)(eid_ptr->Octet + 3);
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                                 struct rt_measure_cca_report * pReport =
1621                                     (struct rt_measure_cca_report *) pReportBuf;
1622                                 ptr = (u8 *)(eid_ptr->Octet + 3);
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                                 struct rt_measure_rpi_report * pReport =
1634                                     (struct rt_measure_rpi_report *) pReportBuf;
1635                                 ptr = (u8 *)(eid_ptr->Octet + 3);
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;
1646
1647                 default:
1648                         break;
1649                 }
1650                 eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
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  */
1669 static BOOLEAN PeerTpcReqSanity(struct rt_rtmp_adapter *pAd,
1670                                 void * pMsg,
1671                                 unsigned long MsgLen, u8 *pDialogToken)
1672 {
1673         struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg;
1674         u8 *pFramePtr = Fr->Octet;
1675         BOOLEAN result = FALSE;
1676         struct rt_eid * eid_ptr;
1677
1678         MsgLen -= sizeof(struct rt_header_802_11);
1679
1680         /* skip category and action code. */
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
1691         eid_ptr = (struct rt_eid *) pFramePtr;
1692         while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1693                ((u8 *)pFramePtr + MsgLen)) {
1694                 switch (eid_ptr->Eid) {
1695                 case IE_TPC_REQUEST:
1696                         result = TRUE;
1697                         break;
1698
1699                 default:
1700                         break;
1701                 }
1702                 eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
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  */
1722 static BOOLEAN PeerTpcRepSanity(struct rt_rtmp_adapter *pAd,
1723                                 void * pMsg,
1724                                 unsigned long MsgLen,
1725                                 u8 *pDialogToken,
1726                                 struct rt_tpc_report_info * pTpcRepInfo)
1727 {
1728         struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg;
1729         u8 *pFramePtr = Fr->Octet;
1730         BOOLEAN result = FALSE;
1731         struct rt_eid * eid_ptr;
1732
1733         MsgLen -= sizeof(struct rt_header_802_11);
1734
1735         /* skip category and action code. */
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
1746         eid_ptr = (struct rt_eid *) pFramePtr;
1747         while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1748                ((u8 *)pFramePtr + MsgLen)) {
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;
1759                 }
1760                 eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
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  */
1777 static void PeerChSwAnnAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
1778 {
1779         struct rt_ch_sw_ann_info ChSwAnnInfo;
1780         struct rt_frame_802_11 * pFr = (struct rt_frame_802_11 *) Elem->Msg;
1781         u8 index = 0, Channel = 0, NewChannel = 0;
1782         unsigned long Bssidx = 0;
1783
1784         NdisZeroMemory(&ChSwAnnInfo, sizeof(struct rt_ch_sw_ann_info));
1785         if (!PeerChSwAnnSanity(pAd, Elem->Msg, Elem->MsgLen, &ChSwAnnInfo)) {
1786                 DBGPRINT(RT_DEBUG_TRACE,
1787                          ("Invalid Channel Switch Action Frame.\n"));
1788                 return;
1789         }
1790
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"));
1798                         return;
1799                 }
1800
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);
1805
1806                 Channel = pAd->CommonCfg.Channel;
1807                 NewChannel = ChSwAnnInfo.Channel;
1808
1809                 if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0)
1810                     && (Channel != NewChannel)) {
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. */
1813                         AsicSwitchChannel(pAd, 1, FALSE);
1814                         AsicLockChannel(pAd, 1);
1815                         LinkDown(pAd, FALSE);
1816                         MlmeQueueInit(&pAd->Mlme.Queue);
1817                         BssTableInit(&pAd->ScanTab);
1818                         RTMPusecDelay(1000000); /* use delay to prevent STA do reassoc */
1819
1820                         /* channel sanity check */
1821                         for (index = 0; index < pAd->ChannelListNum; index++) {
1822                                 if (pAd->ChannelList[index].Channel ==
1823                                     NewChannel) {
1824                                         pAd->ScanTab.BssEntry[Bssidx].Channel =
1825                                             NewChannel;
1826                                         pAd->CommonCfg.Channel = NewChannel;
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));
1835                                         break;
1836                                 }
1837                         }
1838
1839                         if (index >= pAd->ChannelListNum) {
1840                                 DBGPRINT_ERR(("&&&&&&&&&&&&&&&&&&&&&&&&&&PeerChSwAnnAction(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum));
1841                         }
1842                 }
1843         }
1844
1845         return;
1846 }
1847
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  */
1859 static void PeerMeasureReqAction(struct rt_rtmp_adapter *pAd,
1860                                  struct rt_mlme_queue_elem *Elem)
1861 {
1862         struct rt_frame_802_11 * pFr = (struct rt_frame_802_11 *) Elem->Msg;
1863         u8 DialogToken;
1864         struct rt_measure_req_info MeasureReqInfo;
1865         struct rt_measure_req MeasureReq;
1866         MEASURE_REPORT_MODE ReportMode;
1867
1868         if (PeerMeasureReqSanity
1869             (pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReqInfo,
1870              &MeasureReq)) {
1871                 ReportMode.word = 0;
1872                 ReportMode.field.Incapable = 1;
1873                 EnqueueMeasurementRep(pAd, pFr->Hdr.Addr2, DialogToken,
1874                                       MeasureReqInfo.Token, ReportMode.word,
1875                                       MeasureReqInfo.ReqType, 0, NULL);
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  */
1892 static void PeerMeasureReportAction(struct rt_rtmp_adapter *pAd,
1893                                     struct rt_mlme_queue_elem *Elem)
1894 {
1895         struct rt_measure_report_info MeasureReportInfo;
1896         struct rt_frame_802_11 * pFr = (struct rt_frame_802_11 *) Elem->Msg;
1897         u8 DialogToken;
1898         u8 *pMeasureReportInfo;
1899
1900 /*      if (pAd->CommonCfg.bIEEE80211H != TRUE) */
1901 /*              return; */
1902
1903         pMeasureReportInfo = kmalloc(sizeof(struct rt_measure_rpi_report), GFP_ATOMIC);
1904         if (pMeasureReportInfo == NULL) {
1905                 DBGPRINT(RT_DEBUG_ERROR,
1906                          ("%s unable to alloc memory for measure report buffer (size=%zu).\n",
1907                           __func__, sizeof(struct rt_measure_rpi_report)));
1908                 return;
1909         }
1910
1911         NdisZeroMemory(&MeasureReportInfo, sizeof(struct rt_measure_report_info));
1912         NdisZeroMemory(pMeasureReportInfo, sizeof(struct rt_measure_rpi_report));
1913         if (PeerMeasureReportSanity
1914             (pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReportInfo,
1915              pMeasureReportInfo)) {
1916                 do {
1917                         struct rt_measure_req_entry *pEntry = NULL;
1918
1919                         /* Not a autonomous measure report. */
1920                         /* check the dialog token field. drop it if the dialog token doesn't match. */
1921                         if ((DialogToken != 0)
1922                             && ((pEntry = MeasureReqLookUp(pAd, DialogToken)) ==
1923                                 NULL))
1924                                 break;
1925
1926                         if (pEntry != NULL)
1927                                 MeasureReqDelete(pAd, pEntry->DialogToken);
1928
1929                         if (MeasureReportInfo.ReportType == RM_BASIC) {
1930                                 struct rt_measure_basic_report * pBasicReport =
1931                                     (struct rt_measure_basic_report *) pMeasureReportInfo;
1932                                 if ((pBasicReport->Map.field.Radar)
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);
1945                                 }
1946                         }
1947                 } while (FALSE);
1948         } else
1949                 DBGPRINT(RT_DEBUG_TRACE,
1950                          ("Invalid Measurement Report Frame.\n"));
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  */
1968 static void PeerTpcReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
1969 {
1970         struct rt_frame_802_11 * pFr = (struct rt_frame_802_11 *) Elem->Msg;
1971         u8 *pFramePtr = pFr->Octet;
1972         u8 DialogToken;
1973         u8 TxPwr = GetCurTxPwr(pAd, Elem->Wcid);
1974         u8 LinkMargin = 0;
1975         char RealRssi;
1976
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. */
1980
1981         RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0),
1982                                ConvertToRssi(pAd, Elem->Rssi1, RSSI_1),
1983                                ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
1984
1985         /* skip Category and action code. */
1986         pFramePtr += 2;
1987
1988         /* Dialog token. */
1989         NdisMoveMemory(&DialogToken, pFramePtr, 1);
1990
1991         LinkMargin = (RealRssi / MIN_RCV_PWR);
1992         if (PeerTpcReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken))
1993                 EnqueueTPCRep(pAd, pFr->Hdr.Addr2, DialogToken, TxPwr,
1994                               LinkMargin);
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  */
2010 static void PeerTpcRepAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
2011 {
2012         u8 DialogToken;
2013         struct rt_tpc_report_info TpcRepInfo;
2014         struct rt_tpc_req_entry *pEntry = NULL;
2015
2016         NdisZeroMemory(&TpcRepInfo, sizeof(struct rt_tpc_report_info));
2017         if (PeerTpcRepSanity
2018             (pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &TpcRepInfo)) {
2019                 pEntry = TpcReqLookUp(pAd, DialogToken);
2020                 if (pEntry != NULL) {
2021                         TpcReqDelete(pAd, pEntry->DialogToken);
2022                         DBGPRINT(RT_DEBUG_TRACE,
2023                                  ("%s: DialogToken=%x, TxPwr=%d, LinkMargin=%d\n",
2024                                   __func__, DialogToken, TpcRepInfo.TxPwr,
2025                                   TpcRepInfo.LinkMargin));
2026                 }
2027         }
2028
2029         return;
2030 }
2031
2032 /*
2033         ==========================================================================
2034         Description:
2035                 Spectrun action frames Handler such as channel switch annoucement,
2036                 measurement report, measurement request actions frames.
2037
2038         Parametrs:
2039                 Elme - MLME message containing the received frame
2040
2041         Return  : None.
2042         ==========================================================================
2043  */
2044 void PeerSpectrumAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
2045 {
2046
2047         u8 Action = Elem->Msg[LENGTH_802_11 + 1];
2048
2049         if (pAd->CommonCfg.bIEEE80211H != TRUE)
2050                 return;
2051
2052         switch (Action) {
2053         case SPEC_MRQ:
2054                 /* current rt2860 unable do such measure specified in Measurement Request. */
2055                 /* reject all measurement request. */
2056                 PeerMeasureReqAction(pAd, Elem);
2057                 break;
2058
2059         case SPEC_MRP:
2060                 PeerMeasureReportAction(pAd, Elem);
2061                 break;
2062
2063         case SPEC_TPCRQ:
2064                 PeerTpcReqAction(pAd, Elem);
2065                 break;
2066
2067         case SPEC_TPCRP:
2068                 PeerTpcRepAction(pAd, Elem);
2069                 break;
2070
2071         case SPEC_CHANNEL_SWITCH:
2072
2073                 PeerChSwAnnAction(pAd, Elem);
2074                 break;
2075         }
2076
2077         return;
2078 }
2079
2080 /*
2081         ==========================================================================
2082         Description:
2083
2084         Parametrs:
2085
2086         Return  : None.
2087         ==========================================================================
2088  */
2089 int Set_MeasureReq_Proc(struct rt_rtmp_adapter *pAd, char *arg)
2090 {
2091         u32 Aid = 1;
2092         u32 ArgIdx;
2093         char *thisChar;
2094
2095         MEASURE_REQ_MODE MeasureReqMode;
2096         u8 MeasureReqToken = RandomByte(pAd);
2097         u8 MeasureReqType = RM_BASIC;
2098         u8 MeasureCh = 1;
2099         u64 MeasureStartTime = GetCurrentTimeStamp(pAd);
2100         struct rt_measure_req MeasureReq;
2101         u8 TotalLen;
2102
2103         struct rt_header_802_11 ActHdr;
2104         u8 *pOutBuffer = NULL;
2105         int NStatus;
2106         unsigned long FrameLen;
2107
2108         NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer);        /*Get an unused nonpaged memory */
2109         if (NStatus != NDIS_STATUS_SUCCESS) {
2110                 DBGPRINT(RT_DEBUG_TRACE,
2111                          ("%s() allocate memory failed \n", __func__));
2112                 goto END_OF_MEASURE_REQ;
2113         }
2114
2115         ArgIdx = 1;
2116         while ((thisChar = strsep((char **)&arg, "-")) != NULL) {
2117                 switch (ArgIdx) {
2118                 case 1: /* Aid. */
2119                         Aid = (u8)simple_strtol(thisChar, 0, 16);
2120                         break;
2121
2122                 case 2: /* Measurement Request Type. */
2123                         MeasureReqType = simple_strtol(thisChar, 0, 16);
2124                         if (MeasureReqType > 3) {
2125                                 DBGPRINT(RT_DEBUG_ERROR,
2126                                          ("%s: unknow MeasureReqType(%d)\n",
2127                                           __func__, MeasureReqType));
2128                                 goto END_OF_MEASURE_REQ;
2129                         }
2130                         break;
2131
2132                 case 3: /* Measurement channel. */
2133                         MeasureCh = (u8)simple_strtol(thisChar, 0, 16);
2134                         break;
2135                 }
2136                 ArgIdx++;
2137         }
2138
2139         DBGPRINT(RT_DEBUG_TRACE,
2140                  ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", __func__,
2141                   Aid, MeasureReqType, MeasureCh));
2142         if (!VALID_WCID(Aid)) {
2143                 DBGPRINT(RT_DEBUG_ERROR,
2144                          ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
2145                 goto END_OF_MEASURE_REQ;
2146         }
2147
2148         MeasureReqMode.word = 0;
2149         MeasureReqMode.field.Enable = 1;
2150
2151         MeasureReqInsert(pAd, MeasureReqToken);
2152
2153         /* build action frame header. */
2154         MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0,
2155                          pAd->MacTab.Content[Aid].Addr, pAd->CurrentAddress);
2156
2157         NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11));
2158         FrameLen = sizeof(struct rt_header_802_11);
2159
2160         TotalLen = sizeof(struct rt_measure_req_info) + sizeof(struct rt_measure_req);
2161
2162         MakeMeasurementReqFrame(pAd, pOutBuffer, &FrameLen,
2163                                 sizeof(struct rt_measure_req_info), CATEGORY_RM, RM_BASIC,
2164                                 MeasureReqToken, MeasureReqMode.word,
2165                                 MeasureReqType, 0);
2166
2167         MeasureReq.ChNum = MeasureCh;
2168         MeasureReq.MeasureStartTime = cpu2le64(MeasureStartTime);
2169         MeasureReq.MeasureDuration = cpu2le16(2000);
2170
2171         {
2172                 unsigned long TempLen;
2173                 MakeOutgoingFrame(pOutBuffer + FrameLen, &TempLen,
2174                                   sizeof(struct rt_measure_req), &MeasureReq,
2175                                   END_OF_ARGS);
2176                 FrameLen += TempLen;
2177         }
2178
2179         MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, (u32)FrameLen);
2180
2181 END_OF_MEASURE_REQ:
2182         MlmeFreeMemory(pAd, pOutBuffer);
2183
2184         return TRUE;
2185 }
2186
2187 int Set_TpcReq_Proc(struct rt_rtmp_adapter *pAd, char *arg)
2188 {
2189         u32 Aid;
2190
2191         u8 TpcReqToken = RandomByte(pAd);
2192
2193         Aid = (u32)simple_strtol(arg, 0, 16);
2194
2195         DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d\n", __func__, Aid));
2196         if (!VALID_WCID(Aid)) {
2197                 DBGPRINT(RT_DEBUG_ERROR,
2198                          ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
2199                 return TRUE;
2200         }
2201
2202         TpcReqInsert(pAd, TpcReqToken);
2203
2204         EnqueueTPCReq(pAd, pAd->MacTab.Content[Aid].Addr, TpcReqToken);
2205
2206         return TRUE;
2207 }