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